1.这个错误常见于代码行数比较多的时候
int *p1 = (int *)malloc(sizeof(20));
int *p2 = (int *)malloc(sizeof(50));
//若干行代码
p2 = p1;
free(p1);
free(p2);
代码解析:p1和p2在开始都被指向了两块显式申请的堆内存,但是若干行代码后,由于粗心让p1指向的内容也赋给了p2,这就导致p2原来指向的那块空间被泄漏了,并且最后由于这个粗心的程序员没有意识到内存泄漏的问题,还以为两个指针都指向不同的内容,所以对着两个指针指向的内存进行了free,那么问题来了,两个指针指向同一块内存,两次释放会造成什么后果呢?答案是未定义,编译器会直接报错!
2.这个错误就很隐晦了,一般也比较常见于新手程序员。
void GetMemory(int *p)
{
p=(int *)malloc(sizeof(10));
}
int main(void)
{
int *p;
GetMemory(p);
strcpy(p,"hello world!");
printf("%s\n",p);
return 0;
}
代码解析:这段代码会输出什么?会打印出hello world!
吗?如果你回答会,那么你就要好好复习函数和指针部分的内容了,这段代码有两个错误和两个不好的习惯:
不良习惯①:定义指针p的时候没有将指针初始化,这样就导致指针的指向是不确定的(非法的),可以称作野指针。
不良习惯②:申请的内存在main函数结束的时候没有显式释放,虽然程序结束的时候会隐式释放掉申请的内存,但是良好的编程习惯告诉我们,使用完申请的内存就要释放掉,避免内存泄漏,并且释放后要将指针置为NULL,避免出现野指针。
错误①:函数传参的时候应该传一个二级指针,因为实际上传一级指针我们也可以理解为是传值,只不过这值是地址而已,GetMemory函数的在传参的时候会形成一个实参的拷贝,也就是指针p的拷贝,然后用这个指针p的拷贝在函数体中进行一系列操作,而函数中给这个指针的拷贝分配的内存并没有影响外部的指针p,也就是说指针p在外部依然是指向一块非法的内存,那么自然strcpy函数调用就会出错,因为它试图访问一段非法的内存。
错误②:既然函数GetMemory并没有起到名称应有的效果,那么它分配的内存跑哪里去了呢?答案就是泄漏掉了。
3.这个错误就更加隐晦了。。。
//括号内代码在程序代码中也许会重复n次
{
int *p=(int *)malloc(sizeof(100));
p++;
}
free(p);
代码解析:这么显著的错误就不需要说了吧。。。
4.终极错误
/* 假装有代码 */
代码解析:由于程序员的粗心,忘记释放曾经申请过的堆内存,导致内存泄漏。
写在最后:心法大于技法,避免内存泄漏的唯一诀窍就是:养成良好的编程习惯,细心谨慎,那么内存泄漏和野指针就会与你很难再见了。