第41课 - 内存操作经典问题分析一
第41课 - 内存操作经典问题分析一
1. 野指针
(1)野指针指的是 指针变量的值是非法的内存地址,操作野指针会导致程序运行出错。
野指针不是NULL指针而是指向了非法地址;NULL指针并没有危害而且很好判断和调试。
(2)C语言中无法判断一个指针所保存的地址是否合法
(3)野指针产生的原因 ※ 写程序时一定要考虑下面这些注意点
● 局部指针变量没有被初始化。局部指针变量存储在栈上,如果没有初始化,指针变量的值是"垃圾值"。
● 指针所指向的变量在指针使用之前已经被销毁了,典型的例子就是返回局部变量或者局部数组,具体原因可以参考 第39课 - 程序中的三国天下
● 使用 malloc() 申请的动态内存在被 free() 掉之后,仍然使用已经释放过的指针
● 进行了错误的指针运算,比如越界访问内存
● 进行了错误的强制类型转换,比如 int *p = (int *)123456;
【野指针初探】
1 #include <stdio.h> 2 #include <malloc.h> 3 4 5 int main() 6 { 7 int* p1 = (int*)malloc(40); // 分配40字节 8 int* p2 = (int*)1234567; // 错误的强制类型转换, 123456是一个非法地址 9 int i = 0; 10 11 for(i = 0;i < 40; i++) 12 { 13 *(p1 + i) = 40 - i; // p1只分配了40字节,这里越界访问(40 * 4)字节 14 } 15 16 free(p1); 17 18 for(i = 0; i < 40; i++) 19 { 20 p1[i] = p2[i]; // p1越界访问 + p1已经释放,p2非法内存 21 } 22 23 return 0; 24 }
2. 基本原则
(1)绝不返回局部变量和局部数组的地址
(2)任何变量在定以后必须初始化为 0
(3)字符数组必须以 '\0' 结束符后才能成为字符串
(4)任何使用与内存操作相关的函数必须指定长度信息
【无处不在的野指针】
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <string.h> 4 5 struct Student 6 { 7 char* name; 8 int number; 9 }; 10 11 char* func() 12 { 13 char p[] = "Hello World!"; 14 return p; // 返回局部数组 15 } 16 17 void del(char* p) 18 { 19 printf("%s\n", p); 20 free(p); 21 } 22 23 int main() 24 { 25 struct Student s; // 结构体没有初始化 26 char* p = func(); // 返回局部的数组地址 27 28 // strcpy(s.name, p); // s结构体中的name是野指针 29 30 s.number = 99; // 合法 31 32 p = (char*)malloc(5); 33 34 strcpy(p, "Hello World!"); // 内存越界访问 35 36 del(p); 37 38 return 0; 39 }
内存错误是实际产品开发中最常见的问题,然而绝大多数的bug都可以通过遵循基本的编程原则和规范来避免。因此,在学习的时候要牢记和理解内存操作的基本原则、目的和意义!!!
1