本溪山火明火扑灭因为程序员管理错了堆内存而导致的BUG,是C语言最常见、也最难搞的BUG。
它把一个堆内存的指针放在一个类的成员变量里,利用局部对象离开作用域时的析构函数,来完成堆内存的释放。
所以C++的效率比其他语言快得多,因为局部对象什么时候离开作用域,是可以在编译时就确定的,不需要在运行时做额外的处理。
写过C语言的都知道,多线程的野指针是非常难查的BUG,因为程序跑飞了不知道会core在哪里,而且BUG也不是必现的。
因为程序员知道多线程+竞争条件+野指针==随机crash+ 事后找不到第一现场[捂脸]
main()函数返回时也是它们离开作用域的时候,所以在main函数的结尾自动添加释放代码,程序员就不用手动释放内存了。
创建一个对象分两步:第一步调用malloc()申请内存,第二步调用构造函数__init()初始化内存。
即使在源代码层面这时m0, m1, m2依然处于main()函数的作用域内,但对后端来说它们已经离开作用域了,因为之后的基本块都不再使用它们了。
所以,对m0, m1, m2的释放代码,应该加在第8和第9号基本块之间。
对m3的释放代码可以放在第9和第10之间,之后不会再使用m3了:这会让m3-data的引用计数-1。
这时,内存数据有且只有1个引用计数(一开始自带1个),同时有且只有指针dd指向它。
指针dd的释放在for循环之后,即第10和11之间:这里的释放会让引用计数减少到0。
3)什么时间离开作用域,也就是后续不再使用对象变量,要把引用计数-1,如果减少之后为0,就调用free().
前面的mat对象的成员指针m3-data,就是需要跨函数分析的指针。
成员变量在构造函数返回时依然有效,所以要把它是malloc()申请的这个信息,传递到更上层的函数。
3)在释放m3时,析构函数把引用计数-1之后,引用计数才不为0:内存依然是有效的,这时指针dd依然指向它。
抽象语法树AST上的每一个函数调用,必然有一个主调函数、有一个被调函数。
以malloc为起点、main为终点,做图的宽度优先搜索,就可以获取整个调用链。
不能用深度优先搜索(DFS),因为一个上层函数可能调用多个下层函数,而这多个下层函数里都malloc了内存。
如果是DFS,分析顺序是A-D,这样D调用B而申请的内存就会被漏过去了。
如果是BFS,分析顺序是A-B-C-D-E,这样任何函数申请的内存如果传递给上层,(在分析上层函数时)都不会被漏过去。
用do while循环检查内存的传递情况,记录传递的变量和计数,直到不再发生变化为止。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
超全整理!汇总3大指南,讲清会阴裂伤的分级、预防、缝合和修补4大核心问题!
全国人大常委会关于《中华人民共和国香港特别行政区维护国家安全法》第十四条和第四十七条的解释
深圳一高烧患者因“过号”与医生争执头部受伤,医院回应“没有无缘无故的冲突”
消息称苹果已搁置14.1英寸mini-LED 材质 iPad Pro的发布计划
|