野指针之2

本文深入解析野指针的概念,探讨野指针产生的原因及其潜在的危害。文中详细介绍了如何通过良好的编程习惯来避免野指针的产生,特别是使用malloc和free进行内存管理时需要注意的事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.何为野指针?

野指针指指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。

解释一下:

malloc 和 free 是在系统的栈上分配空间。
malloc是申请,意思就是告诉系统,我要用一块RAM,给我用了别人就不要用了。
free是释放,意思是告诉系统,给我的这块RAM我用完了,不再用了,系统可以把它干别的了。free()释放的是指针指向的内存。并不是说,free()解除了原来指向这块内存的指针与这块内存地址之间的联系,联系依然存在,这就可能导致误用出错,所以需要在free之后置NULL,这样就解除关联了
free之后,系统还没有拿这块RAM干别的事之前,这块RAM的内容可能是不会变的,依然可以读出原来的内容,因为你的指针a还是指向这块RAM。但要注意,这块RAM已经不属于你了,读一下内容无所谓,如果往里面写就很危险了。
如果程序定义了一个指针,就必须要立即让它指向一个我们设定的空间或者把它设为NULL,如果没有这么做,那么这个指针里的内容是不可预知的,即不知道它 指向内存中的哪个空间(即野指针),它有可能指向的是一个空白的内存区域,可能指向的是已经受保护的区域,甚至可能指向系统的关键内存,如果是那样就糟 了,也许我们后面不小心对指针进行操作就有可能让系统出现紊乱,死机了。所以我们必须设定一个空间让指针指向它,或者把指针设为NULL,这是怎么样的一 个原理呢,如果是建立一个与指针相同类型的空间,实际上是在内存中的空白区域中开辟了这么一个受保护的内存空间,然后用指针来指向它,那么指针里的地址就 是这个受保护空间的地址了,而不是不可预知的啦,然后我们就可以通过指针对这个空间进行相应的操作了;如果我们把指针设为NULL,我们在头文件定义中的 #define NULL 0 可以知道,其实NULL就是表示0,那么我们让指针=NULL,实际上就是让指针=0,如此,指针里的地址(机器数)就被初始化为0了,而内存中地址为0 的内存空间……不用多说也能想象吧,这个地址是特定的,那么也就不是不可预知的在内存中乱指一气的野指针了。

  还应该注意的是,free和delete只是把指针所指的 内存给释放掉,但并没有把指针本身干掉。指针p被free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不 把p设置为NULL,会让人误以为p是个合法的指针。用free或delete释放了内存之后,就应立即将指针设置为NULL,防止产生“野指针”。内存 被释放了,并不表示指针会消亡或者成了NULL指针。(而且,指针消亡了,也并不表示它所指的内存会被自动释放。)

指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
指针释放后之后未置空
有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
指针操作超越变量作用域
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
class A {

public:

void Func(void){ cout << “Func of class A” << endl; }

};

class B {

public:

A *p;

void Test(void) {

A a;

p = &a; // 注意 a 的生命期 ,只在这个函数Test中,而不是整个class B

}

void Test1() {

p->Func(); // p 是“野指针”

}

};

### 指针与悬空指针的概念及区别 #### 指针 指针是指在声明时未被初始化的指针,或者指向的内存地址是无效的。这种指针可能从未指向过有效的内存地址,或者原本指向的内存地址已经变得不可预知。由于指针的值是未定义的,使用它会导致不可预测的行为。 **示例:** ```cpp int* ptr; // 未初始化的指针,此时ptr是一个指针 *ptr = 10; // 使用指针赋值,行为不可预测 ``` #### 悬空指针 悬空指针是指原本指向一个有效的内存地址,但该地址已经被释放或删除,而指针本身没有被置为 `NULL`。此时,指针仍然保存着已经被释放的内存地址,如果尝试访问或修改该内存,会导致未定义行为。 **示例:** ```cpp int* ptr = new int(5); // 动态分配内存 delete ptr; // 释放内存 *ptr = 10; // ptr现在是悬空指针,访问已释放的内存,行为不可预测 ``` #### 指针与悬空指针的区别 1. **来源不同:** - 指针通常是因为指针未初始化或指向的内存从未被分配。 - 悬空指针是因为指针指向的内存已经被释放,但指针没有被置为 `NULL`。 2. **状态不同:** - 指针可能从未指向过有效的内存。 - 悬空指针原本指向有效的内存,但该内存已被释放。 3. **后果相似:** - 无论是指针还是悬空指针,一旦被访问或修改,都会导致未定义行为,可能引发程序崩溃或数据损坏。 #### 如何避免指针和悬空指针 - **初始化指针:** 在声明指针时,尽量将其初始化为 `NULL` 或指向有效的内存。 ```cpp int* ptr = NULL; // 初始化为空指针 ``` - **释放内存后置空指针:** 在释放动态分配的内存后,立即将指针置为 `NULL`,以防止其成为悬空指针。 ```cpp int* ptr = new int(5); delete ptr; ptr = NULL; // 释放后置空指针 ``` - **检查指针有效性:** 在使用指针之前,检查其是否为 `NULL`,确保指针指向有效的内存。 ```cpp if (ptr != NULL) { *ptr = 10; } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值