linux c 常见的错误之存储器

对c语言程序猿来说: 管理和使用虚拟存储器可能是一个容易出错和苦难的任务。与存储器有关的错误属于那些令人费解的错误,因为它经常在时间和空间上,都在距离源一段距离之后,才表现出来。将错误的数据编写到错误的位置上,你的程序可能在最终失败之前运行好几个小时或好几天,且使程序中止的位置同错误的位置已经很远,下面将举例说明一些常见的错误:

间接引用坏指针

在进程的虚拟地址空间中存在较大的未被分配空间,没有映射到任何有意义的数据,如果我们试图间接引用这些信息的指针,那么操作系统就会以段异常中止我们的程序(内存越界访问),而且虚拟存储器的有些区域为只读区域,试图写这些区域也会发生内存保护性错误。
如 常见的间接引用坏指针 scanf, scanf从标准输入中读取一个整数到一个变量中,常见的方法为:
scanf(“%d”,&a);

如果我们写成这样 scanf(“%d”,a) 那么此时系统就会把整型a的内容解析为一个地址传送给变量
此时我们获取变量通常会发生两种错误:
1 程序直接报段错误
2 a整型变量所指向的值为当前进程合法的地址,此时将导致获取变量的值发生错误,可能会产生令人费解的答案。


读未初始化的存储器

通常情况下.bss存储器位置(未初始化的c变量),在加载时会被初始化零,但是对于堆存储器有时候却不一样,
例:一个堆存储器未初始化零
int *m(int **a,int *b,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]*b[j];
return y;
}
以上的例子,正确的操作方式应该赋值 y[i] =0; 不然的话 在y[i] +..时,系统会报数据未定义的错误。

允许栈缓冲区溢出

例:一个输入字符串不检查字符串的大小时就写入栈中的目标缓冲区,那么就会发生缓冲区溢出错误:
void a(){
char buf[64];
gets(buf); //输入超过64个字符将产生错误
return ;
}

指针和它们指向的对象是相同大小的

1 int **m(int m,int n){
2 int i;
3 int **a =(int **)malloc(n*sizeof(int));

4 for(i=0;i
造成错位错误

错位错误是一种常见的覆盖错误:
1 int **m(int m,int n){
2 int i;
3 int **a =(int **)malloc(n*sizeof(int *));

4 for(i=0;i
引用指针,被错误的操作对象,或操作错误的对象



误解指针运算


指针的算术操作是以它们指向的对象的大小为单位来进行的。
而这种大小并不一定是字节,如下所示:
函数的目的是扫描一个int数组,并返回一个指针,指向val的首次出现:
int *s(int *a,int val){
while(*a && *a !=val)
a +=sizeof(int);
return a;
}
这个遍历的错误之处在于,每循环一次就跳过了4条记录。


引用不存在的变量

int *t(){
int b;
return &b;
}
这个函数返回一个指针,指向栈里的一个局部变量,尽管b也指向一个合法的存储器地址,但是它已经不再指向一个合法的变量,当以后程序中有其它函数这个地址上的值时,可给程序带来某明奇妙的错误。

引用空闲堆块中的数据

malloc free 后再引用刚刚分配空间的变量,将会产生错误。


存储器泄漏

malloc分配内存后未释放

相关阅读:
malloc free函数的用法
malloc的使用方法及注意事项
为什么要使用动态存储器分配(malloc)