第42课 - 内存操作经典问题分析二
第42课 - 内存操作经典问题分析二
1. 常见内存错误
(1)结构体成员指针未初始化
(2)结构体成员指针未分配足够的内存
(3)内存分配成功但并未初始化
(4)内存操作越界
【常见内存错误1】
1 #include <stdio.h> 2 #include <malloc.h> 3 4 void test(int* p, int size) // 对内存操作时,有带长度信息 5 { 6 int i = 0; 7 for(i = 0; i<size; i++) 8 { 9 printf("%d\n", p[i]); 10 } 11 12 free(p); // 不合符谁申请谁释放原则 13 } 14 15 void func(unsigned int size) 16 { 17 int* p = (int*)malloc(size * sizeof(int)); 18 int i = 0; 19 20 if(size % 2 != 0) // 当size为奇数时会产生内存泄漏 21 { 22 return; 23 } 24 25 for(i=0; i<size; i++) 26 { 27 p[i] = i; 28 printf("%d\n", p[i]); 29 } 30 31 free(p); 32 } 33 34 int main() 35 { 36 int* p = (int*)malloc(5 * sizeof(int)); 37 38 test(p, 5); // test内部释放了p所指内存,不符合谁申请谁释放原则 39 40 free(p); // 重复释放p ==> Error in `./a.out': double free or corruption (fasttop): 0x0000000001c29010 41 // 在main函数动态申请的内存应该在main函数中释放,谁申请谁释放 42 43 func(9); // 参数为奇数 ==> 产生内存泄漏 44 func(10); // 正常 45 46 return 0; 47 }
【常见内存错误2】
1 #include <stdio.h> 2 #include <malloc.h> 3 4 struct Demo 5 { 6 char* p; 7 }; 8 9 int main() 10 { 11 struct Demo d1; // 结构体未被初始化,d1.a是野指针 12 struct Demo d2; 13 14 char i = 0; 15 16 for(i='a'; i< 'z'; i++) 17 { 18 d1.p[i] = i; // d1.p是野指针,这里将产生段错误 19 } 20 21 d2.p = (char*)calloc(5, sizeof(char)); 22 23 printf("%s\n", d2.p); 24 25 for(i='a'; i< 'z'; i++) 26 { 27 d2.p[i] = i; // 前面使用calloc只分配了5个字节,但是 'a'~'z'是26个字节,越界访问 28 } 29 30 free(d2.p); 31 32 return 0; 33 }
2. 内存操作的交通规则
(1)动态内存申请之后,应该立即检查指针值是否为NULL,防止使用NULL指针
(2)free指针之后必须立即赋值为NULL
(3)任何与内存操作相关的函数都必须带长度信息
(4)malloc操作和free操作必须匹配,遵循谁申请谁释放的原则,不要跨函数释放,防止内存泄漏和多次释放
● 当 malloc 的次数多于 free 时,会产生内存泄漏
● 当 malloc 的次数少于 free 时,程序可能崩溃