关于野指针及指针所指内存被回收后的一些误区

野指针与内存管理
本文探讨了内存回收的本质,即内存空间并非被清空,而是变得可再利用。通过实例解析了野指针的概念,即指向已释放内存的指针,并提供了避免野指针的方法,即将指针设置为NULL。

我们是不是经常会有这样的疑问: 内存空间被回收是不是这块内存空间被清空了?何为野指针 ,怎样避免野指针?

    //在堆内存申请一块内存 32位 4字节,64位 8字节 的空间 ,定义一个指针变量 p 指向这块空间

    int * p  = (int *)malloc(sizeof(int));

 //给变量p所指的变量地址赋值

    *p = 10;

    // free(p)回收p所指的内存 注意 : 回收内存的空间,只是说这块空间可以再被利用了,并不是这块空间的数据被清空了,这块空间还储存的是10的变量。执行free(p)这一句代码后的p就是野指针;

    free(p);

    cout << "&p is  ----  before"<< &p<<endl;

    cout << "p is ----  before"<< p <<endl;

此时打印结果 :

&p is  ----  before 0x7ffeefbff508

p is ----  before 0x102802d00

 //此时的p指向的地址仍然是10所在的内存地址,但这块址已被回收了此时的p就是一个野指针 。 由此可见 野指针 :指向一个已被回收/释放的内存地址的指针 

   //为避免野指针,应该加上这一句

    p = NULL ;

    cout << "&p is ----  after "<< &p<<endl;

    cout << "p is ----  after "<< p <<endl;

此时打印结果 :

&p is ----  after 0x7ffeefbff508

p is ----  after 0x0

些时p被赋为NULL,为一个空指针。

因为 p是定义的一个指针变量,是存在栈中的,函数没执行完 p的地址是不会被清空 &p的值才没有改变。

 

转载于:https://www.cnblogs.com/jdxiao/p/10058611.html

<think>嗯,用户现在问的是关于C语言指针的详解。之前已经给过他们一个C语言的学习规划,里面提到指针是基础阶段的重要内容,用户可能已经按照那个规划在学习,现在遇到了指针的问题,需要更深入的解释。 首先,我需要回顾用户的历史提问,确保这次回答和之前的建议保持一致。用户之前的学习规划分为四个阶段,指针在基础阶段和系统深入阶段都有涉及。现在用户需要详细解释指针,可能他们在学习过程中遇到了困难,或者想巩固理解。 接下来,我需要考虑用户的需求。他们可能对指针的概念、用法、常见问题等有疑问。作为新手,指针可能是一个比较难理解的概念,特别是内存地址指针运算、指针与数组的关系这些点。需要详细但清晰地解释,避免使用过于专业的术语,同时结合实际例子。 用户可能还有更深层的需求,比如如何避免指针常见错误,如内存泄漏、指针等。所以在回答中不仅要解释概念,还要给出实用的建议和注意事项。另外,用户可能对指针的应用场景感兴趣,比如动态内存分配、函数指针等,这些在实际项目中的用途需要举例说明。 需要检查之前的回答是否已经覆盖了这些内容。在之前的规划里,提到了指针的基础和进阶内容,但这次需要更深入。所以需要展开每一个子主题,确保每个部分都有足够的解释和示例代码。例如,指针的基本概念需要解释变量、地址指针变量的定义和使用,可能用图示或比喻来帮助理解。 同时,要注意用户可能的常见误区。比如,指针和数组名的区别,指针的运算,多级指针的理解,以及函数指针的用法。这些都需要详细说明,并指出常见的错误例子,比如越界访问、悬空指针等。 还要考虑资源推荐,是否需要推荐相关的书籍或在线资料,帮助用户进一步学习。之前已经推荐过《C和指针》这本书,可以再次提及,强调它的实用性。 最后,总结部分需要强调练习的重要性,鼓励用户多写代码,通过实际项目来巩固指针的使用。同时提醒注意事项,如初始化指针、避免内存泄漏等,帮助用户养成良好的编程习惯。</think>以下是对C语言指针的全面解析,包含核心概念、使用场景、易错点及实践建议,采用分层讲解方式: --- ### 一、指针的本质(内存视角) 1. **内存地址可视化** ```c int a = 10; printf("变量值:%d\n", a); // 输出:10 printf("内存地址:%p\n", &a); // 输出类似:0x7ffd42d3a4cc ``` - 每个变量占用连续内存空间(`sizeof(int)`通常为4字节) - `&`运算符获取变量首字节地址 2. **指针变量定义** ```c int *p = &a; // p存储a的地址 *p = 20; // 通过指针修改a的值 ``` - 类型声明`int *`表示"指向int的指针" - `*`符号在不同位置含义不同: - 声明时:标识指针类型 - 使用时:解引用操作 --- ### 二、指针操作核心场景 #### 场景1:数组遍历 ```c int arr[5] = {1,2,3,4,5}; int *ptr = arr; // 等价于 &arr[0] // 通过指针偏移访问元素 for(int i=0; i<5; i++){ printf("%d ", *(ptr + i)); } ``` - 指针算术运算特性:`ptr+1`实际移动`sizeof(int)`字节 - 数组名本质:编译期确定的常量指针(不可修改) #### 场景2:动态内存管理 ```c int *dynamic_arr = (int*)malloc(5 * sizeof(int)); if(dynamic_arr == NULL) { // 处理分配失败 } // 使用后必须释放 free(dynamic_arr); dynamic_arr = NULL; // 防止悬空指针 ``` - 堆内存生命周期:手动控制(与栈内存自动回收对比) #### 场景3:函数参数传递 ```c void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int x=10, y=20; swap(&x, &y); // 实现值交换 ``` - 对比值传递:避免大结构体复制开销 - 多级指针应用(如修改指针本身): ```c void alloc_mem(int **p, int size) { *p = (int*)malloc(size * sizeof(int)); } ``` --- ### 三、指针进阶应用 #### 1. 函数指针 ```c int add(int a, int b) { return a + b; } int (*func_ptr)(int, int) = &add; // 声明函数指针 printf("%d", func_ptr(3,5)); // 输出8 ``` - 典型应用:回调函数、策略模式实现 #### 2. 结构体指针 ```c typedef struct { char name[20]; int age; } Person; Person p1 = {"Alice", 25}; Person *ptr = &p1; printf("Name: %s", ptr->name); // 箭头运算符访问成员 ``` #### 3. 指针与字符串 ```c char *str = "Hello"; // 字符串常量(只读) char arr[] = "World"; // 可修改的字符数组 // 常见操作 char *p = strchr(str, 'e'); // 查找字符位置 ``` --- ### 四、指针安全与常见错误 #### 危险操作示例: ```c // 示例1:指针 int *danger_ptr; *danger_ptr = 10; // 未初始化的指针 // 示例2:越界访问 int arr[3] = {1,2,3}; int *p = arr; *(p + 5) = 10; // 非法内存写入 // 示例3:双重释放 int *p = malloc(sizeof(int)); free(p); free(p); // 导致程序崩溃 ``` #### 防御性编程建议: 1. 初始化指针时立即赋值`NULL` 2. 使用`assert(p != NULL)`进行安全检查 3. 遵循谁分配谁释放原则 4. 使用工具检测: ```bash valgrind --leak-check=full ./your_program ``` --- ### 五、指针理解技巧 1. **绘图法**:在纸上画出内存布局图 ``` [0x1000] int a = 10 [0x1004] int *p = 0x1000 ``` 2. **类型转换实验**: ```c float f = 3.14; int *p = (int*)&f; printf("%x", *p); // 观察浮点数的二进制表示 ``` 3. **调试器观察**:使用GDB查看内存内容 ```gdb (gdb) x/4xb 0x1000 # 查看4个字节的内存内容 ``` --- ### 六、学习路线建议 1. 先掌握基础指针操作(变量/数组) 2. 再理解指针内存管理的关系 3. 最后攻克函数指针/多级指针 4. 推荐练习: - 实现链表数据结构 - 编写内存复制函数`memcpy` - 创建函数指针数组实现状态机 **核心要点**:指针本质是内存地址的抽象,理解`变量↔地址↔值`的三元关系是掌握指针的关键。每行涉及指针的代码都要清楚内存发生了什么变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值