第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

posted @ 2019-11-13 23:09  Hengs  阅读(295)  评论(0编辑  收藏  举报