寻找快速而又脏的方法来识别构造函数(或任何函数)的调用者我正在编写宏来帮助识别内存泄漏,方法是将this
指针转储到OutputDebugString
。
知道调用ctor和dtor的位置有助于识别问题。
TNX \ 0
答案 0 :(得分:8)
如果你正在使用visual studio,你可以附加调试器,而不是让断点有一个跟踪点。您可以通过右键单击断点并选择When Hit...
来执行此操作。然后选择打印包含堆栈跟踪的消息。此消息将发送到输出窗格,您可以随意分析所有呼叫。
答案 1 :(得分:6)
我能想到的最好方法是在调试器中运行程序并在构造函数中放置断点。接下来,检查调用堆栈。
如果要在一个特定类中定位一个特定分配,可以保留分配计数并查看哪些分配编号未被释放。再次运行程序,并打破正确的分配编号。
如果您需要将调用堆栈转储到日志中,我知道可以使用例如win32 API生成堆栈转储。更通用的方法是将显式调用堆栈保持为全局/线程特定状态,例如在std::vector<std::string>
- 对象中。 (使用RAII确保每个push_back
都附带pop_back
)
答案 2 :(得分:3)
好像你在Windows上(OutputDebugString)。因此,您可以使用StackWalk64 api来获取堆栈跟踪。 有关详细信息,请参阅“Printing the stack trace in C++ (MSVC)”问题。
还有很多可用的泄漏检测工具(BoundsChecker等)。
答案 3 :(得分:2)
没有快速而肮脏的方法,C ++不提供任何可移植的方式来查看堆栈跟踪。如果你想搜索内存泄漏,我建议你研究valgrind
和类似的工具,它们做得很好。作为编码指南,首先使用RAII避免内存泄漏(始终拥有资源的所有者)。
答案 4 :(得分:1)
使用gcc?为什么不generate a stack trace?
答案 5 :(得分:1)
如果你正在使用Linux,那么Valgrind会做你想要的一切,甚至更多。我觉得在用C ++开发时它是必不可少的。
答案 6 :(得分:0)
您在Windows下运行? Visual Leak Detector过去曾帮助我找到内存泄漏。
使用RAII也有助于减少内存泄漏。
如果您有冒险精神,那么您可以重载新功能和删除功能。 Paul Nettle does this in his MMGR
答案 7 :(得分:0)
答案 8 :(得分:0)
答案 9 :(得分:0)
使用调试器和调用堆栈的建议是合理的,可能是最好的解决方案。但是,如果您没有调试器,那将无济于事。
您知道构造函数使用的calling convention吗?如果是这样,您可以使用一些内联汇编程序(假设您的编译器支持它)来检查函数调用的顺序。使用std调用,Win32最常见的约定,弹出堆栈将显示指向调用函数后返回的地址的指针(即调用函数中的某个位置)。这并不理想,但您可以从那一点开始倒退,直到找到一个您知道是函数开头的地址。这里唯一的问题是你需要获得所有函数的地址才能做到这一点......这可以通过一个简单的技巧来完成,将eip的值放到函数顶部的另一个寄存器中,然后将此值移动到一个数组中,以便稍后在调试时进行检查,类似于(intel语法):
call label
label:
pop eax
mov [address of next array entry], eax
答案 10 :(得分:0)
如果您正在使用g ++,则可以构建您的项目以进行覆盖。当您运行一些示例代码时,您可以使用gcov查看程序的覆盖范围。
此输出包含调用树,您应该能够看到对构造函数的调用以及调用它们的函数。
我能想到的唯一缺点是你只能获得实际执行的代码的输出,因此你需要有很好的测试用例。话虽如此,无论如何,进行覆盖率分析是值得的。最后,我强烈建议您使用lcov查看结果!
答案 11 :(得分:0)
感谢大家的反馈。在ctor中设置断点不是一种选择,因为即使在程序的短生命周期内也会有数百次调用新对象。
在ctor和dtor中跟踪宏可以解决这个问题。
Visual Leak Detector和Stackwalk64看起来很有前途
还找到了AfxDumpStack(AFX_STACK_DUMP_TARGET_ODS); // OutputDebugString
但它非常嘈杂