我正在编写全局删除/新运算符的调试版本,以检测内存泄漏,双重删除和删除未分配的内存。
就“new”运算符而言,我覆盖了全局新运算符并使用宏传递了文件名和行号信息。重写的“new”运算符将地址中的内存地址,文件名,大小和行号信息存储在地图中。
我也覆盖了“删除”操作符,从地图中删除了已删除的地址'条目。现在我想将删除的内存信息存储在另一个地图中,该地图存储了调用“删除”的文件名和行号信息。
但是delete运算符只接受参数(要删除的对象的内存地址)。 有人可以告诉如何检测代码中的双删除吗?
答案 0 :(得分:6)
您已经在重载new
内创建了已分配内存地址(键)和文件名,行号(值字段)的映射。
在重载删除时,只需检查您创建的地图中是否存在传递的地址。
如果是,您认为对delete
的通话有效,并从地图中删除该地址条目。
如果否,则将删除调用视为有问题,delete called on a pointer not allocated through your new
或trying to call delete multiple times
。
答案 1 :(得分:2)
如果你需要的是区分双删除和永久分配内存中的删除,只需将地址映射到已分配内存的 state ,而不是从地图中删除元素,只需更新 state 将其标记为已发布。每次删除中的测试将验证地址是否存在(如果不是错误正在删除从未分配的地址),如果是,则是否已经释放了内存(如果有,则错误是双重释放)。
答案 2 :(得分:0)
有两个不同的问题:检测双重删除(相反
删除从未分配的内存,并确定其中的位置
它发生的程序。
首先,我的调试operator new
之前分配了保护区
然后它返回(也用于检测写过去的块)
以解除分配结束);我在operator
delete
中将它们设置为不同的模式,并检查此模式。总有机会
永远不会分配内存可能包含这种模式,但机会是
非常非常小。
确定错误发生在代码中的哪个位置更加困难。
我编写了一个堆栈回溯的代码,但它是非常系统的
依赖。 (我在Sparc上有Solaris版本,在Intel上有Linux版本,以及
Windows。)它报告的所有内容都是十六进制的返回地址;取决于
程序员使用其他工具分析这些工具。 GNU binutils
package有一个程序addr2line
,在Linux下运行良好,但是
考虑到有序地图,手动操作并不困难。