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);
}
return p;
}
上述代码中p加4,意思是指向当前对象之后的第四个对象,而不是下一个对象。
6.引用不存在的变量
典型错误:在定义的一个函数中,当我们定义了一个局部变量,然后在函数返回的时候返回这个局部变量的地址 原因是:局部变量存放在栈中,函数调用结束,那么这个函数中定义的局部变量的生存期就到了,就会被释放,如果我们还返回一个局部变量的地址,等于返回了一个失效地址,并没有什么意义,甚至会给程序带来重大问题。
7.使用malloc造成的内存问题
(1)引用已经调用free()函数释放的块 (2)使用malloc之后并不释放,造成内存泄漏
|