使用/不使用视觉检漏仪的C ++中的内存泄漏检测 [英] memory leak detecting in C++ with/without Visual Leak Detector

查看:92
本文介绍了使用/不使用视觉检漏仪的C ++中的内存泄漏检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检测我的C ++程序在Windows中的内存泄漏。
我还阅读了MSDN上有关 mermoy的文档泄漏检测 ,我也开始使用Visual Leak Detector。



我对泄漏报告有疑问。
我期望一个带有行号的文件名,但我总是报告下面的文本。
它有泄漏描述的所有组件(块类型,内存地址,数据等)
除了文件名和行号。



如果是真正的泄漏?
如果是,你知道为什么文件/行不报告?
在此期间,我还看看此网址



感谢

 
检测到内存泄漏!
转储对象 - >
{4723}正常块在0x04AFB5B8,8个字节长。
数据:2C 3F 00 00 28 3F 00 00
{1476}正常块在0x04AC3B58,12字节长。
数据:00 CD CD CD EB 01 75 4C CA 3D 0B 00
对象转储完成。


解决方案

我研究了很多不同的跟踪内存泄漏的方法。



为了理解他们的优点和缺点,我们必须了解不同的机制和要求:


  1. 如何新建,删除,malloc和免费拦截?一些工具使用#define重新定义new,delete,malloc和free,但这依赖于include文件的正确顺序,并且如果一个类包含例如。一个称为自由的方法(如Qt中的情况)。预处理器还将重新定义此方法,这可能导致编译错误或未解决的外部。



    另一种方式是推翻全局新建和删除操作符。这是一个更清洁的解决方案,但失败是你有一个第三方库,在库中添加一个新的,但删除的标题(反之亦然)。


  2. 如何确定呼叫的来源。如果使用#define拦截new,delete,...,通常预处理符号 __ FILE __ __ LINE __ 得到泄漏的源头。但是,如果你在代码中有通用函数,例如。 CreateString(),那么大多数泄漏将在这些通用函数中报告,这不会真正帮助你。



    另一种方法是在运行时获取调用堆栈。它可以很容易做到使用Windows StackWalk功能,但在我的经验,这是非常非常慢。一个更快的选择是直接获取基指针,并依赖于栈帧指针(必须使用/ Oy-编译以获取堆栈帧指针)。你可以像这样得到框架(基本)指针:_asm mov DWORD PTR [FramePtr],ebp 。然后简单循环并在循环中从((ADDR *)FramePtr)[1]; 获取指令指针,并从 FramePtr获取下一个帧指针=((ADDR *)FramePtr)[0];


  3. 如何报告确切时刻的泄漏。在我的情况下,我想要在应用程序结束时报告泄漏,但是为了能够这样做,您需要在应用程序结束时使用泄漏报告机制。这意味着如果你想自己报告泄漏,你需要依赖于在应用程序结束时被销毁的全局变量(并报告全局变量的析构函数中的泄漏)。对于服务器类型的应用程序,您可能更有兴趣在两个时间点之间获得内存使用的差异。


现在不同的泄漏系统:


  1. C RunTime:报告泄漏到底,调用堆栈。


  2. 外部Microsoft实用程序(如GFlags,UMDH ,, ...):他们似乎只能记录两个时间点之间的差异。但是,调用堆栈看起来好多了,虽然GFlags实用程序可能会在操作系统中设置标志,可能会导致应用程序严重减慢。


  3. Visual检漏仪。似乎正确找到所有泄漏,但在我的情况下它不工作,因为我有一个第三方DLL,只是中止其进程的DllUnload(似乎是一个Windows 7的具体问题)。


  4. 我个人最喜欢的(人们不会同意我的说法,我敢肯定),是写你自己的内存管理器。拦截可以很容易地使用全局新的和删除操作符(与上面提到的可能的问题),你可以得到如上所述的调用堆栈。此替代方案还依赖于能够在应用程序的最后一刻执行的代码。


选择一种替代方法,我发现以下方面对我的情况非常重要:




  • 我希望它在我的应用程序中无缝工作,如果有泄漏,开发人员立即通知。如果您将泄漏检查延迟到以后使用Purify等外部实用程序的时候,泄漏查找将会更加困难。

  • 我希望在应用程序结束时报告泄漏,


  • 我希望尽可能多的信息泄露(数据,调用堆栈...)
  • b

    希望这有助于。


    I want to detect memory leaks of my C++ program in Windows. I read the documentation also on MSDN about mermoy leak detection and I also started using Visual Leak Detector.

    I have a doubt about the reporting of the leaks. I am expecting a file name with a line number, but I am always reported the text below. It has all the component of a leak description ( block type, memory address, data, etc..) except for the file name and the line number.

    If it is a real leak? If yes do you know why the file/line are not reported? In the meantime I am having a look also at this url

    Thanks

    Detected memory leaks!
    Dumping objects ->
    {4723} normal block at 0x04AFB5B8, 8 bytes long.
     Data:  2C 3F 00 00 28 3F 00 00 
    {1476} normal block at 0x04AC3B58, 12 bytes long.
     Data:  00 CD CD CD EB 01 75 4C CA 3D 0B 00 
    Object dump complete.
    

    解决方案

    I investigated quite some different ways of tracking memory leaks. They all have their advantages but also their disadvantages.

    To understand their advantages and disadvantages, we have to understand the different mechanisms and requirements:

    1. How are new, delete, malloc and free intercepted? Some tools use #define to redefine new, delete, malloc and free, but this relies on the correct order of the include files, and may give problems if a class contains e.g. a method called free (as is the case in Qt). The preprocessor will also redefine this method, which may lead to compilation errors or unresolved externals.

      Another way is to overrule the global new and delete operators. This is a much cleaner solution, but fails is you have a 3rd party library that puts a new in the library, but the delete in the header (or vice versa).

    2. How is the source of the call determined. If new,delete,... are intercepted using #define's, often the preprocessor symbols __FILE__ and __LINE__ are uses to get the source of the leak. However, if you have 'generic' functions in your code like e.g. CreateString(), then most of the leaks will be reported in these generic functions, which does not really help you.

      An alternative is to get the call stack at run time. It can be quite easily done using the Windows StackWalk function, but in my experience, this is very very slow. A much faster alternative is to get the base-pointer directly, and to rely on the stack-frame-pointers (you must compile with /Oy- to get the stack-frame-pointers). You can get the frame (base) pointer like this: _asm mov DWORD PTR [FramePtr], ebp. Then simply loop and in the loop get the instruction pointer from ((ADDR *)FramePtr)[1]; and the next frame-pointer fromFramePtr = ((ADDR *)FramePtr)[0];

    3. How to report the leaks at the exact moment. In my case, I want the leaks to be reported at the end of the application, but to be able to do this, you need a leak-reporting mechanism at the end of your application. This means that if you want to report your leaks yourself, you need to rely on global variables being destructed at the end of your application (and report the leaks in ths destructor of the global variable). For server-type applications, you are probably more interested in getting the difference in memory usage between two points in time.

    And now the different leak-systems:

    1. C RunTime: reports leaks at the end, but has no decent way of reporting call stacks. Its method of intercepting calls to new,delete,... may cause problems in combinations with 3rd party libraries (like Qt, Boost, ...)

    2. External Microsoft utilities (like GFlags, UMDH,, ...): they seem to be able to only log differences between two points in time. However, the call stack seems to be much better, although the GFlags utility may set flags in the OS that may cause a serious slowdown of your application.

    3. Visual Leak Detector. Seems to correctly find all leaks, but in my case it doesn't work since I have a 3rd party DLL that simply aborts the process at its DllUnload (seems to be a Windows 7 specific problem).

    4. My personal favorite (and people will not agree with me, I'm sure), is to write your own memory manager. Intercepting can be easily done using global new and delete operators (with the possible problems mentioned above), and you can get the call stack as described above. This alternative also relies on being able to have code that is executed at the very last moment in your application.

    When choosing an alternative, I found the following aspects very imporant for my situation:

    • I want it to work seemlessly in my application, so that every developer is notified immediately if there is a leak. If you delay leak-checking to a later moment where you use external utilities like Purify, leak-finding will be much harder.
    • I want leaks to be reported at the end of the application, automatically.
    • I want as much as possible information from the leak (the data, the call stack, ...)

    Hope this helps.

    这篇关于使用/不使用视觉检漏仪的C ++中的内存泄漏检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆