我们有自己的智能指针类,使用基本的AddRef和Release来计算引用。
在调试时,我能够看到很多对象没有被正确释放。我可以看到哪些对象没有被释放但很难找到它们从哪个地方被分配。
有没有好的设计模式来解决这个问题?
我已经调试了调试语句和ADDREF和RELEASE,并且在调用release时我可以看到引用计数。在某些情况下,它超过1,这意味着指针不会被删除。
如果我开始在shared_ptr const上放置断点,那么它将调用数百次并且难以查明内存泄漏。
看起来有些循环引用被创建导致这些泄漏。
答案 0 :(得分:2)
请勿使用设计模式。不要仅为了检测泄漏而添加代码膨胀。
使用记忆工具。想到了Valgrind,以及一些适用于Windows的商业用途。
也...
我可以看到哪些对象没有被释放但很难找到它们从哪个地方被分配。
为什么呢?在对象的构造函数中设置断点。或者使用标准指针(std::shared_ptr
,std::unique_ptr
)。
我已经调试了调试语句和ADDREF和RELEASE,并且在调用release时我可以看到引用计数。在某些情况下,它超过1,这意味着指针不会被删除。
您是否正在考虑复制省(RVO / NRVO)?这似乎更有可能是原因。
答案 1 :(得分:1)
多年前,在auto_ptr
之前,我编写了自己的智能指针类,我们在代码库中广泛使用了它。当然,它充满了虫子。
我有完全相同的问题。虽然我无法向您展示我用于识别源自资源泄漏的呼叫站点的实际代码(因为代码不再存在),但我可以告诉您我做了什么。
第一件事是我写了一个#define
宏> SHUDDER<,类似于我概述的那个here,我可以使用它代替new
来分配我的对象。宏向智能指针发送附加参数,指示文件&呼叫站点的行号。智能指针会保留它。
然后,当我发出new
启用此功能的神奇咒语时,我用我的宏替换了全局#defines
。显然,这应该在所有Releasse构建中禁用,并且仅在您实际调试 this 时才在Debug构建中使用。
然后我让我的程序运行,直到我想要看到所有呼叫站点。我在那里的智能指针上执行dump_call_sites()
方法,将static
vector
个调用站点字符串转储到stdout。因此发现了问题,我将所有这些神奇的咒语都归还给所有这些神奇的咒语。
这是真正的hack-n-slash codiing。它远非优雅,它引入了它自己的一系列问题。但随着printf
调试,它有它的位置。如果您不想或不想加载Rational Purify或Bounds Checker类型的产品,这可以帮助您快速确定泄漏的来源。