这些都是最近在《深入理解计算机系统》中看到的,在项目中确实很实用
1.间接引用坏指针
在进程的虚拟地址空间中有较大的洞,没有映射任何有意义的数据,如果我们试图间接引用一个指向这些洞的指针,那么操作系统就会以段异常来终止我们的程序。而且,虚拟存储器的某些区域是只读的,试图写这些区域将造成以保护异常终止这个程序。
eg: scanf("%d", &val) 然而,对于C程序员初学者而言(对有经验者也是如此!), 很容易传递val的内容,而不是它的地址: scanf("%d", val)
在这种情况下,scanf将把val的内容解释成一个地址,并试图将一个字写到这个位置。在最好的情况下,程序立即以异常终止。最糟糕的情况下,val的内容对应于虚拟存储器的某个合法的读写区域,于是我们就覆盖了存储器,这通常会在相当以后造成灾难性的、令人困惑的后果
2.读为初始化的存储器
malloc的对存储器未初始化为0,建议使用calloc
3.允许栈缓冲区溢出
程序不检查输入串的大小就写入栈中的目标缓冲区,那么这个程序就会有缓冲区溢出错误
void bufoverflow()
{
char buf[64];
gets(buf);
return;
}建议将gets换成fgets函数,这个函数限制了输入串的大小
4.假设指针和它们指向的对象是相同大小的
将sizeof(int *)写成了sizeof(int),这个在不同机器上体现的不同
5.造成错位错误
6.引用指针,而不是它所指向的对象
*size-- 由于×与--优先级相同,从右向左结合,这是减少的是指针自己的值,而不是它所指向的整数的值
7.误解指针运算
p +=sizeof(int) 不等于 p++
8.引用不存在的变量
int *stackref()
{
int val;
return &val;
}这个函数返回一个指针(比如说是p),指向栈内的一个局部变量,然后弹出它的栈帧。尽管p仍然指向一个合法的存储器地址,但是它已经不再指向一个合法的变量了。当以后在程序中调用其他函数时,存储器将重用他们的栈帧。后来,如果程序分配某个值给*p,那么它可能实际正在修改另一个函数的栈帧中的一个条目,从而带来潜在的灾难性后果
9.引用空闲堆块中的数据
引用已经释放的存储器
10.引起存储器泄漏
malloc后没有free,多次malloc堆里就会充满了垃圾