C程序中常见的与存储器有关的错误

  csapp的第九章“虚拟存储器”往往被认为是全书最精华的部分之一。书里前言也写道:“这一章比其他任何一章都更能展现将计算机系统中的硬件和软件结合起来阐述的优点”。在这一章,作者以malloc的实现为例,讲解了动态存储器分配、碎片合并、垃圾回收这些概念。最后列举了十种C程序中容易犯的内存引用错误,很实用:)总结如下。

  • 间接引用坏指针
  • 读未初始化的存储器
  • 允许栈缓冲区溢出
  • 错误地假设指针和它们指向的对象是相同大小的
  • 造成错位错误
  • 引用指针,而不是它所指向的对象
  • 误解指针运算
  • 引用不存在的变量
  • 引用空闲堆块中的数据
  • 引起存储器泄漏

  • 间接引用坏指针
scanf("%d",&val);//正确,应当传递给scanf变量地址

scanf("%d",val);//错误,scanf会将val值解释为地址,假设不幸的是val的值确实对应于虚存的合法读写区域,就覆盖了存储器

  • 读未初始化的存储器
int *matvec(int **A, int *x, int n)
{
    int i, j; 
    int *y = (int *) malloc(n *sizeof(int)); 
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            y[i] += A[i][j] * x[j];/* 程序不正确地假设向量y被初始化为零(堆存储器不会初始化为零)*/
        }
    }
}

  • 允许栈缓冲区溢出
void bufoverflow()  
{  
    char buf[64];  

    gets(buf); /* 不检查输入串的大小就写入栈中的目标缓冲区会导致缓冲区溢出。应使用限制输入串大小的fgets函数 */  
    return;  
}

  • 错误地假设指针和它们指向的对象是相同大小的

int **makeArray1(int n, int m)  
{  
    int i;  
    int **A = (int **) malloc(n * sizeof(int)); /*应是sizeof(int *),否则创建的是int数组而不是指针数组*/

    for (i = 0; i < n; i++)  
        A[i] = (int *)malloc(m * sizeof(int));  

    return A;  
}  
/*这段代码将创建一个由n个指针组成的数组,每个指针指向一个包含m个int的数组*/

/*这段代码只有在int和指向int的指针大小相同的机器上运行良好,在指针大于int的机器上会引发for循环写越界*/

  • 造成错位错误
int **makeArray2(int n, int m)  
{  
    int i;  
    int **A = (int **) malloc(n *sizeof(int *));  

    for (i = 0; i <= n; i++)  /*低级的越界错误,i < n 而不是i <= n */
        A[i] = (int *) malloc(m * sizeof(int));  

    return A;  
}  

  • 引用指针,而不是它所指向的对象
int *binheapDelete(int **binheap, int *size)  
{  
    int *packet = binheap[0];  

    binheap[0] = binheap[*size - 1];  
    *size--;          /*注意运算符优先级--和*相同,导致指针自减。应是 (*size)-- */  
    heapipfy(binheap, *size, 0);  
    return (packet);  
}  

  • 误解指针运算
int *search(int *p, int val)  
{  
    while (*p && *p != val)  
        p += sizeof(int); /* 指针是以指向的对象大小为单位来进行算术操作的。遍历数组应是p++。*/  

    return p;  
}  

  • 引用不存在的变量
int *stackref()  
{  
    int val;  

    return &val; /* 注意局部变量的生存周期 */ 
}  

  • 引用空闲堆块中的数据
int *heapref(int n, int m)  
{  
    int i;  
    int *x, *y;  

    x = (int *) malloc(n *sizeof(int));   

    free(x);  

    y = (int *) malloc m * sizeof(int));  

    for (i = 0; i < m, i++)  
        y[i] = x[i]++; /* x已经被释放 */  

    return y;  
}  

  • 引起存储器泄漏
void leak(int n)  
{  
    int *x = (int *)malloc(n *sizeof(int));  

    return; /* 未释放就返回导致x成为堆中的垃圾 */  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值