如何在C ++中检测内存泄漏的真实位置? [英] How can i detect the real location of memory leak in C++?

查看:140
本文介绍了如何在C ++中检测内存泄漏的真实位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含内存泄漏的C ++应用程序,尽管我使用的是"Leakdiag"和"LDGrapher",但我找不到泄漏的位置?!
我还使用"_CrtDumpMemoryLeaks()"函数,该函数给我这样的结果:

I have a C++ application which contains a memory-leak, although I am using "Leakdiag" and "LDGrapher", I can''t locate where the leak is?!
I''m also using "_CrtDumpMemoryLeaks()" function which give me results like this:

Detected memory leaks!
Dumping objects ->
{657} normal block at 0x00D93B98, 52 bytes long.
 Data: < N   N          > D8 4E D9 00 D8 4E D9 00 00 00 00 00 CD CD CD CD
{656} normal block at 0x00D93AF0, 108 bytes long.
 Data: <(        ;  (   > 28 F0 12 00 00 00 00 00 98 3B D9 00 28 F0 12 00
{655} normal block at 0x00D94ED8, 52 bytes long.
 Data: < ;   ;          > 98 3B D9 00 98 3B D9 00 CD CD CD CD CD CD CD CD
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\occcont.cpp(923) : {641} normal block at 0x00D92100, 12 bytes long.
 Data: <            > F6 06 0A 00 00 00 00 00 00 00 00 00


推荐答案

遇到泄漏时,我使用的方法都是手动的-没有任何工具.
重要的是:您不必查找泄漏即可进行修复.
查找malloc()调用(和朋友:calloc, realloc, strdup):用堆栈变量替换尽可能多的调用,并用智能指针(例如std::auto_ptr)替换所有其他变量.无论您在哪里进行堆分配,都应添加一个带有很好借口的注释:缓冲区的最大大小直到运行时才知道,或者该函数实际上是一个工厂,其目的是分配和初始化对象.
查找使用newdelete的地方,就像它们是mallocfree一样.请使用std::auto_ptr.
寻找全局指针.消灭他们.

最后,您不仅可以解决漏洞,而且可以提高整体代码质量.

只是我的两位,
The way I used, when confronted with a leak, was all manual - no tools.
The important thing is: you don''t have to find the leak in order to fix it.
Look for malloc() calls (and friends: calloc, realloc, strdup): replace as many of them as possible by stack variables, and all the others by smart pointers (std::auto_ptr,. for instance). Wherever you keep a heap allocation, add a comment with a really good excuse: the maximum size of a buffer is not known until run time, or the function is actually a factory whose purpose is to allocate and initialize an object.
Look for places where new and delete are used as if they were malloc and free. Use std::auto_ptr instead.
Look for global pointers. Destroy them.

In the end you''ll have not only fixed the leak, but you''ll have improved overall code quality.

Just my two bits,


避免内存泄漏的最快方法是首先不要使它们泄漏.真的没有理由再手动管理内存了,这有点麻烦了.

也就是说,您可以尝试一些方法而无需深入研究标准库源代码(nv3对运行时堆的结构了解甚多):

-使用new查找您正在使用的所有地点.当您找到它们时:-

(a)确定对象是否可以堆栈分配(特别是Java程序员是new进行所有操作且不使用RAII的专家).如果可以用堆栈对象替换它们,请这样做!

(b)将所有代表所有权的原始指针替换为std::unique_ptrstd::shared_ptrstd::vector

(c)删除编译器现在抱怨的所有delete

-仪器new delete.制作一个内存块计数器类,您可以在作用域中声明该类,以查看其中是否可能发生泄漏.在单元测试中使用它,它将显示是否有对象正在泄漏所包含的对象.

-仪器选择类的构造函数和析构函数.通过选择与丢失的块大小大致相同的块来选择它们.保持连续构造的对象总数,并减去被破坏的对象数量.如果在程序运行期间发现构造了多余的对象,则可以将问题缩小到new ed类的对象.

-如果丢失了存储块,则与前一个存储块有关,请查看转储块的第一个字.如果它看起来像一个指针,则可能是该类的vtable的地址-如果您有任何虚函数.如果您感觉很勇敢,则可以使用映射文件(链接器命令行上的/MAP:filename)将地址与类相关联.

-如果要获取翻译单元中特定类或所有类的内存布局(方便查看块并查看是否能识别其中的内容并找到vtable ptr),请使用/d1reportAllClassLayout/dreportSingleClassLayout<class name=""></class>编译器命令行

嗯,那是我的事,希望您能尽快解决.
The quickest way to avoid memory leaks is to not make them in the first place. There''s really no reason to manually manage memory any more, it''s a bit of a mug''s game.

That said there are a few of things you can try without digging into the standard library source code (nv3 knows more than I do about the structure of the runtime heap):

- Find all the places you''re using new. When you find them:-

(a) work out if the object can be stack allocated instead (Java programmers in particular are buggers for newing everything and not using RAII). If you can replace them with stack objects do so!

(b) replace any raw pointers that represent ownership with std::unique_ptr, std::shared_ptr or std::vector

(c) remove all the deletes that that the compiler is now complaining about

- Instrument new and delete. Make a memory block counter class which you can declare in scopes to see if a leak potentially occurs in there. Use it in your unit tests and it''ll show up if an object is leaking a contained object.

- Instrument selected class''s constructors and destructor. Select them by choosing ones that are about the same size as the blocks that are being lost. Keep a running total of objects constructed and subtract the number of objects destructed. If over the run of your program you find there are excess objects constructed you can narrow the problem down to where objects of that class are newed.

- Related to the previous one if you''ve got a lost memory block have a look at the first word of the dumped block. If it looks like a pointer it could be the address of the class''s vtable - if you have any virtual function. If you''re feeling brave you might be able to correlate the address with a class using a map file (/MAP:filename on the linker command line).

- If you want to get the memory layout of a particular class or all classes in a translation unit (handy for looking at your blocks and seeing if you recognise anything in there and finding the vtable ptr) use /d1reportAllClassLayout or /dreportSingleClassLayout<class name=""></class> on the compiler command line

Er, that''s about it from me, hope you sort it out soon.


花括号中的数字(如{657})会提示您发生的时间和地点.这些是分配请求编号.因此,每一个分配都会获得一个新的数字,通过该数字,您可以跟踪事物.

如果可以在DEBUG模式下重现内存泄漏,并且泄漏总是以相同的请求号发生,则可以使用以下技术:

-在_heap_alloc_dbg函数的dbgheap.c中在以下行上设置断点:

The numbers in curly braces like {657} give you a hint where and when it happens. These are the allocation request numbers. So every single allocation gets a new number and by this number you can track things.

If you can reproduce the memory leak in DEBUG mode and the leaks occur always with the same request numbers you can use the following technique:

- set a breakpoint in dbgheap.c in function _heap_alloc_dbg on the line that says:

lRequest = _lRequestCurr;



不必在VC ++安装中查找该文件,您同样可以在任意new 语句中设置断点,并逐步深入研究,直到获得函数_heap_alloc_dbg.然后找到上面的行并在其中设置一个断点.

-将此条件设置为仅触发您要查找的请求号的条件断点

-运行程序;希望您能落在断点上

-查看调用堆栈,找出实际发起此内存分配请求的原因

这不是一个真正容易的技术,但是在某些困难的情况下非常有用.



Instead of looking for that file in your VC++ installation you can equally well set a breakpoint an arbitrary new statement and drill down with step-into until you arrive at function _heap_alloc_dbg. Then find the above line and set a breakpoint there.

- make this a conditional breakpoint that only triggers for the request number you are looking for

- run your program; hopefully you will land on your breakpoint

- look at the call stack and find out what actually initiated this memory allocation request

It''s not a really easy technique, but very helpful in some of the hard cases.


这篇关于如何在C ++中检测内存泄漏的真实位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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