• 欢迎访问C语言网www.dotcpp.com 比赛栏每月有奖月赛!举办比赛联系QQ:2045302297
  • 问题反馈、粉丝交流 QQ群327452739 蓝桥杯训练群:113766799 申请群时请备注排名里的昵称
  • C语言研究中心 为您提供有图、有料、解渴的C语言专题! 欢迎讨论!

C语言free释放内存后为什么指针里的值不变?竟然还可以输出?

C语言研究中心 CTO 20092次浏览 3个评论

想必大家都知道C语言中动态开辟内存之后,必须要释放内存,来防止内存泄露。也就是malloc之后,必须要free。正所谓”有借有还,再借不难”, 不少同学会问为什么释放指针后,指向这块内存的指针的值不变呢,我们今天为大家揭秘。

 

首先,我们用malloc开辟一个内存,用strcpy拷贝一串字符串,然后释放掉,通过断点调试进行观察!

下图可以看到,在VC6编译环境下,观察指针p的指针所指向的内容已经被strcpy后改变

C语言free释放内存后为什么指针里的值不变?竟然还可以输出?

 

下一步free函数,我们选择F11单步介入观察,幸运的是在VC6中可以看到源代码,如下图,会进入到DBGHEAP.c文件中,会调用_free_dbg函数,继续F11介入观察代码

 

 

C语言free释放内存后为什么指针里的值不变?竟然还可以输出?

 

多次单步之后,我们可以看到一个memset函数,那么F10执行这memset,观察P指向的内容,果然不出我们所料:

0x00970e38处的内容已经被0xDD覆盖,如下图红色字部分。

 

C语言free释放内存后为什么指针里的值不变?竟然还可以输出?

 

这里重点观察了,这个memset函数我们应该很熟悉,第二个参数即为要重置的内容,这里我们可以转到定义 处,或者搜索第二个参数_bDeadLandFill,可以看到有如下定义, 为0xDD

 

C语言free释放内存后为什么指针里的值不变?竟然还可以输出?

 

怎么样,大家看到这里应该明白了吧!

 

我们这里是VC6编译器下的环境,也有部分同学反映free之后内容并未消失,这里我们分析可能是部分编译器free函数实现原理不同,欢迎大家自行尝试,并与我们交流。

而关于free之后,p的之后为何没有改变,仍然还是这个原先堆空间的这个地址,原因在于free函数仅仅是将malloc申请的内存释放回去,所谓的释放也就是告诉编译器,这块内存已经使用完毕,可以收回了。但指针所指向的内存值,并不会发生改变。就可以比方说,你租了一套房子,到期后,房子收回归还房东,而此时你可能还拿着房子的钥匙,这个时候你虽然可以继续访问这个房子(内存),但已经不属于你,是非法的。也可能有新的租客入驻更改房子的内置,也可能还是这个样子。取决于不同的房东(编译器)和租客(内容)。

这就是free释放内存后,指针内地址仍然存在,但有时还可以访问,有时候访问输出乱码或输出其他值的原因。

 

怎么样,大家明白了吗?

有任何问题,或新的发现,欢迎联系我们!

C语言研究中心(www.dotcpp.com)

C语言网提供「C语言、C++、算法竞赛」在线课程,全部由资深研发工程师或ACM金牌大佬亲授课,更科学、全面的课程体系,以在线视频+在线评测的学习模式学习,学练同步,拒绝理论派,真正学会编程!还有奖学金等增值福利等你!

C语言网, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C语言free释放内存后为什么指针里的值不变?竟然还可以输出?
喜欢 (35)
[jinyangH@aliyun.com]
分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
(3)个小伙伴在吐槽
  1. 刚开始申请了100个字节,然后free之后申请的内存空间变成了dd,但是我数来数去填充dd的字节数有104个是怎么回事?
    Nrdesire2016-12-29 03:02 回复
    • debug环境下,编译器会多初始化几个字节,用于检测堆数据是否有越界访问
      CTO2017-02-27 10:54 回复