一、对NULL指针的解引用操作
当我们用malloc函数申请了一块很大的空间,然后没有判断是否申请成功就对指针进行解引用,就有可能产生错误(为NULL指针时)
例如:
#include <stdio.h> #include <stdlib.h> int main() { int* p = (int*)malloc(1000000);//申请一块大空间 /*if (p == NULL) //一般情况我们会判断是否申请成功 { perror("main"); return; }*/ int i = 0; //而此时没有判断就对指针进行解引用 for (i = 0; i < 10; i++) { *(p + i) = i; //导致对NULL指针进行解引用,产生错误 } free(p); p = NULL; return 0; }
二、对动态开辟空间的越界访问
在申请了一块空间且没有去调整其大小的情况下,在使用的过程中使用了超出其空间的情况,即为越界访问内存,也是常见错误之一。
例如:
#include <stdio.h> #include <stdlib.h> int main() { int* p = (int*)malloc(10 * sizeof(int)); //动态开辟一块空间,相当于一个10个整型的数组 if (p == NULL) { perror("main"); return; } int i = 0; for (i = 0; i < 40; i++) //此处的40显然超出了10个整型,会造成越界访问 { *(p + i) = i; } free(p); p = NULL; return 0; }
三、使用free释放非动态开辟内存
#include <stdio.h> #include <stdlib.h> int main() { int arr[10] = { 0 }; int* p = arr; free(p); //错误!! return 0; }
四、使用free释放一块动态开辟内存的一部分
#include <stdio.h> #include <stdlib.h> int main() { int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { perror("main"); return; } int i = 0; for (i = 0; i < 3; i++) { *p++ = i; } free(p); p = NULL; return 0; }
五、多次释放同一块动态开辟的内存
#include <stdio.h> #include <stdlib.h> int main() { int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { perror("main"); return; } free(p); //... //... //... free(p); //错误 return 0; }
为避免出现这种错误,我们在释放完之后将指针p赋为空指针。这样即使二次使用free函数时,传入空指针也是不起任何作用的。
即,
#include <stdio.h> #include <stdlib.h> int main() { int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { perror("main"); return; } free(p); p = NULL; //... //... //... free(p); //free函数什么都不做 return 0; }
六、动态开辟内存忘记释放(内存泄露)
动态开辟的空间,有两种回收方式:
- 主动free
- 程序结束
- 看下面的代码段:
#include <stdio.h> #include <stdlib.h> void test() { int* p = (int*)malloc(5 * sizeof(int)); if (p == NULL) { perror("test"); return; } //... //... //最后忘记释放内存 } int main() { test(); //... //... return 0; }
在test函数中,创建了局部变量p,也在堆区动态开辟了一块空间。最后执行完test函数忘记释放空间,而出了test函数之后,局部变量p销毁,那就再也找不到那块空间的地址,不能再进行释放空间的操作。
即发生了内存泄露。
内存泄漏 (Memory leak)是在 计算机科学 中,由于疏忽或错误造成程序未能释放已经不再使用的 内存 。. 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。