总结C程序中常见的与内存有关的错误

1.引用错误的地址

在日常的程序编写中,容易由于粗心出现的一个问题:没有映射到有真正意义的数据 比如: scanf(“%d”,val); 由于粗心导致我们将val的地址误写为val这个值,那么在执行scanf的时候,就会把val的这个值解释为地址并去寻找这个地址,然后去覆盖那个地址的值。

2.读未初始化的内存

刚接触C语言的同学总会如认为指针所指向的地址的值总是为0,其实并不是这样的,如果没有进行初始化,那么指针指向的地址的值是一个随机值,并不是0

3.内存越界

(1)栈缓冲区溢出 比如程序不检查输入串的大小就直接写入栈中的目标缓冲区,当输入串过大超过目标缓冲区的大小时,就会出现溢出。 (2)由于没有控制好变量的范围导致越界,从而覆盖非法内存的内容 (3)假设指针和它指向的对象是相同大小的 在有些机器上,指针的大小和int类型的大小是不一样的,像Core i7这样的机器上,指针大于int。如果不明确这一定,就容易造成错误。

例如:

int** makeArray(int n,int m)
{
          
   
    int **A(int**)malloc(n*sizeof(int));
    for(int i=0;i<n;++i)
    {
          
   
         A[i]=(int*)malloc(m*sizeof(int));
    }
    return A;
}

在上面的示例中,“ int **A(int**)malloc(n*sizeof(int));”是错误的,应该是: int **A(int**)malloc(n*sizeof(int*)); 错误的代码误认为指针和它所指向的对象相同大小,所以申请了n*sizeof(int)个字节,这里假设n=4,所以申请了16个字节,但是当在Core i7这样的机器上时,指针大于int,本来应该申请的字节大于16,但是写成 int **A(int**)malloc(n*sizeof(int));之后,就只申请了16个字节,申请的空间不足,那么在循环中,将写到超出A数组结尾的地方。

4.引用指针,而不是它所指向的对象

需要注意C操作符的优先级和结合性 比如: size是一个指针,size是这个指针所指向的对象,当执行size–的时候,如果本意是想让size指针所指向的对象的值减一,但是事与愿违,因为星号和减减的优先级相同,从右向左结合,意思就变为:指针减一,然后得出指针所指的对象。 所以需要明确操作符的优先级,避免因此导致错误。

5.误解指针运算

指针都是四个字节,所以指针加一,就是让指针移动大所指类型对象的下一个对象。 比如:

int *fun(int* p,int val)
{
          
   
     while(*p&&*p!=val)
     {
          
   
         p+=sizeof(int);//应该是p+=1;
     }
     return p;
}

上述代码中p加4,意思是指向当前对象之后的第四个对象,而不是下一个对象。

6.引用不存在的变量

典型错误:在定义的一个函数中,当我们定义了一个局部变量,然后在函数返回的时候返回这个局部变量的地址 原因是:局部变量存放在栈中,函数调用结束,那么这个函数中定义的局部变量的生存期就到了,就会被释放,如果我们还返回一个局部变量的地址,等于返回了一个失效地址,并没有什么意义,甚至会给程序带来重大问题。

7.使用malloc造成的内存问题

(1)引用已经调用free()函数释放的块 (2)使用malloc之后并不释放,造成内存泄漏

经验分享 程序员 微信小程序 职场和发展