详解C++ function的生命周期及内存使用方式

记录一个function作用域引发的坑,不了解C++的可以直接看文章后面的多线程内存分析,应该对解bug有所借鉴。

C++中std::function可以对任何代码块进行封装调用,比如普通函数、lambda函数等等,但是对对于类内定义的function在使用类内元素时要注意生命周期的管理,看一下下面的例子:

                     

     

定义一个func类,并在局部代码块里实例化一个对象,将该对象中的function传出给全局变量funcm。当执行完代码块的时候,func对象已经析构了,也就是其申请的内存已经释放了,那么继续执行function调用会是什么情况呢?运行一下看一下:

可以看到Func类虽然结束生命周期释放了自己申请的内存,main函数(主线程)中funcm仍然正确执行了。事实上,func析构确实将自己申请的内存释放了,但是因为是单线程且后续操作未执行malloc申请内存操作(就算申请内存不执行写操作,脏数据仍然在内存中),因此function执行并未出现异常。

那么在局部代码执行完毕后申请内存并写入数据试试:

执行结果如下:

到这里就明白了,同进程内两次申请同样大小的内存肯定会申请到相同虚拟地址,因为对于执行程序的内核而言其内存分配算法是固定的(不管是伙伴算法还是FirstFit等),具体原因大家可以琢磨一下。因此虽然局部函数里面申请的内存释放了,但是后续申请到相同的地址并进行写操作,就会影响function的调用。

多线程访问私有栈

到这里可以延申一下,多余多线程场景,如果某线程读取另一线程的栈数据(非堆数据),是否能正确读取呢?实验一下:

结果如下:

但是这里要注意不能让主线程提前回收子线程资源,也就是需要让子线程睡眠一下,否则会触发段错误。另外,局部变量不一定会保存在栈中,对于调用较多的变量可能保存在寄存器中。

再看一下,子线程申请内存并写入数据,之后释放内存,主线程等待子线程操作完毕后申请同样大小的内存,会发生什么情况呢:

运行结果如下:

可以看到主线程中存有子线程的脏数据。原因是因为多线程是共享TLB表的,对于多进程,因为不同进程有自己的页表,也就是相同虚拟地址会映射到不同物理内存地址,就不会出现这种情况。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值