如何在 C++ 代码/项目中找到内存泄漏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6261201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find memory leak in a C++ code/project?
提问by Chris_vr
I am a C++ programmer on the Windows platform. I am using Visual Studio 2008.
我是 Windows 平台上的 C++ 程序员。我正在使用 Visual Studio 2008。
I usually end up in the code with memory leaks.
我通常会在代码中出现内存泄漏。
Normally I find the memory leak by inspecting the code, but it is cumbersome and is not always a good approach.
通常我通过检查代码来发现内存泄漏,但它很麻烦,并不总是一个好方法。
Since I can't afford a paid memory leak detection tool, I wanted you guys to suggest the best possible ways to avoid memory leaks.
由于我负担不起付费的内存泄漏检测工具,因此我希望你们建议避免内存泄漏的最佳方法。
- I want to the know how the programmer can find memory leaks.
- Is there any standard or procedure one should follow to ensure there is no memory leak in the program?
- 我想知道程序员如何找到内存泄漏。
- 是否应该遵循任何标准或程序来确保程序中没有内存泄漏?
回答by John Smith
Instructions
指示
Things You'll Need
你需要的东西
- Proficiency in C++
- C++ compiler
- Debugger and other investigative software tools
- 精通C++
- C++编译器
- 调试器和其他调查软件工具
1
1
Understand the operator basics. The C++ operator new
allocates heap memory. The delete
operator frees heap memory. For every new
, you should use a delete
so that you free the same memory you allocated:
了解操作员基础知识。C++ 运算符new
分配堆内存。该delete
运营商的FreeS堆内存。对于 each new
,您应该使用 adelete
以便释放您分配的相同内存:
char* str = new char [30]; // Allocate 30 bytes to house a string.
delete [] str; // Clear those 30 bytes and make str point nowhere.
2
2
Reallocate memory only if you've deleted. In the code below, str
acquires a new address with the second allocation. The first address is lost irretrievably, and so are the 30 bytes that it pointed to. Now they're impossible to free, and you have a memory leak:
仅当您已删除时才重新分配内存。在下面的代码中,str
通过第二次分配获取一个新地址。第一个地址不可挽回地丢失了,它指向的 30 个字节也是如此。现在它们无法释放,并且您有内存泄漏:
char* str = new char [30]; // Give str a memory address.
// delete [] str; // Remove the first comment marking in this line to correct.
str = new char [60]; /* Give str another memory address with
the first one gone forever.*/
delete [] str; // This deletes the 60 bytes, not just the first 30.
3
3
Watch those pointer assignments. Every dynamic variable (allocated memory on the heap) needs to be associated with a pointer. When a dynamic variable becomes disassociated from its pointer(s), it becomes impossible to erase. Again, this results in a memory leak:
观看那些指针分配。每个动态变量(堆上分配的内存)都需要与一个指针相关联。当动态变量与其指针脱离关联时,将无法擦除。同样,这会导致内存泄漏:
char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1; // Bad! Now the 40 bytes are impossible to free.
delete [] str2; // This deletes the 30 bytes.
delete [] str1; // Possible access violation. What a disaster!
4
4
Be careful with local pointers. A pointer you declare in a function is allocated on the stack, but the dynamic variable it points to is allocated on the heap. If you don't delete it, it will persist after the program exits from the function:
小心使用本地指针。您在函数中声明的指针在堆栈上分配,但它指向的动态变量在堆上分配。如果你不删除它,它会在程序退出函数后持续存在:
void Leak(int x){
char* p = new char [x];
// delete [] p; // Remove the first comment marking to correct.
}
5
5
Pay attention to the square braces after "delete." Use delete
by itself to free a single object. Use delete []
with square brackets to free a heap array. Don't do something like this:
注意“删除”后的方括号。delete
单独使用以释放单个对象。使用delete []
方括号来释放堆数组。不要做这样的事情:
char* one = new char;
delete [] one; // Wrong
char* many = new char [30];
delete many; // Wrong!
6
6
If the leak yet allowed - I'm usually seeking it with deleaker (check it here: http://deleaker.com).
如果泄漏尚未允许 - 我通常会与 deleaaker 一起寻找它(请在此处查看:http://deleaker.com )。
回答by Nawaz
You can use some techniques in your code to detect memory leak. The most common and most easy way to detect is, define a macro say, DEBUG_NEW and use it, along with predefined macros like __FILE__
and __LINE__
to locate the memory leak in your code. These predefined macros tell you the file and line number of memory leaks.
您可以在代码中使用一些技术来检测内存泄漏。最常见和最简单的检测方法是,定义一个宏,比如 DEBUG_NEW 并使用它,以及预定义的宏,如__FILE__
和__LINE__
来定位代码中的内存泄漏。这些预定义的宏告诉您内存泄漏的文件和行号。
DEBUG_NEW is just a MACRO which is usually defined as:
DEBUG_NEW 只是一个 MACRO,通常定义为:
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
So that wherever you use new
, it also can keep track of the file and line number which could be used to locate memory leak in your program.
因此,无论您在何处使用new
,它还可以跟踪文件和行号,这些文件和行号可用于定位程序中的内存泄漏。
And __FILE__
, __LINE__
are predefined macroswhich evaluate to the filename and line number respectively where you use them!
并且__FILE__
,__LINE__
是预定义的宏,它们分别计算您使用它们的文件名和行号!
Read the following article which explains the technique of using DEBUG_NEW with other interesting macros, very beautifully:
阅读以下文章,它解释了将 DEBUG_NEW 与其他有趣的宏一起使用的技术,非常漂亮:
A Cross-Platform Memory Leak Detector
From Wikpedia,
来自维基百科,
Debug_new refers to a technique in C++ to overload and/or redefine operator new and operator delete in order to intercept the memory allocation and deallocation calls, and thus debug a program for memory usage. It often involves defining a macro named DEBUG_NEW, and makes new become something like new(_FILE_, _LINE_) to record the file/line information on allocation.Microsoft Visual C++ uses this technique in its Microsoft Foundation Classes. There are some ways to extend this method to avoid using macro redefinition while still able to display the file/line information on some platforms. There are many inherent limitations to this method. It applies only to C++, and cannot catch memory leaks by C functions like malloc. However, it can be very simple to use and also very fast, when compared to some more complete memory debugger solutions.
Debug_new 是指 C++ 中的一种技术,用于重载和/或重新定义 operator new 和 operator delete 以拦截内存分配和释放调用,从而调试程序的内存使用情况。它通常涉及定义一个名为 DEBUG_NEW 的宏,并将 new 变成 new(_ FILE_, _ LINE_) 之类的东西来记录分配时的文件/行信息。Microsoft Visual C++ 在其 Microsoft 基础类中使用此技术。有一些方法可以扩展此方法以避免使用宏重定义,同时仍然能够在某些平台上显示文件/行信息。这种方法有许多固有的局限性。它仅适用于 C++,不能通过像 malloc 这样的 C 函数捕获内存泄漏。但是,与一些更完整的内存调试器解决方案相比,它使用起来非常简单,速度也非常快。
回答by Doc Brown
There are some well-known programming techniques that will help you to minimize the risk of getting memory leaks at first hand:
有一些众所周知的编程技术可以帮助您将内存泄漏的风险降至最低:
- if you have to do your own dynamic memory allocation, write
new
anddelete
always pairwise, and make sure the allocation/deallocation code is called pairwise - avoid dynamic memory allocation if you can. For example, use
vector<T> t
whereever possible instead ofT* t = new T[size]
- use "smart pointers" like boost smart pointers (http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
- my personal favorite: make sure you have understood the concept of ownership of a pointer, and make sure that everywhere where you use pointers, you know which code entity is the owner
- learn which constructors / assignment operators are automatically created by the C++ compiler, and what that means if you have class that owns a pointer (or what that means if you have a class that contains a pointer to an object it does notown).
- 如果您必须进行自己的动态内存分配,请编写
new
并delete
始终成对,并确保分配/释放代码成对调用 - 如果可以,请避免动态内存分配。例如,
vector<T> t
尽可能使用而不是T* t = new T[size]
- 使用“智能指针”,如 boost 智能指针(http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
- 我个人的最爱:确保你已经理解了指针所有权的概念,并确保在你使用指针的任何地方,你都知道哪个代码实体是所有者
- 了解哪些构造函数/赋值运算符是由 C++ 编译器自动创建的,以及如果您的类拥有一个指针意味着什么(或者如果您的类包含指向它不拥有的对象的指针,这意味着什么)。
回答by CantGetANick
Valgrind http://valgrind.org/
Valgrind http://valgrind.org/
and
和
回答by Gal Nachmana
Running "Valgrind" can:
运行“Valgrind”可以:
1) Help Identify Memory Leaks- show you how many memory leaks you have, and point out to the lines in the code where the leaked memory was allocated.
1)帮助识别内存泄漏- 向您展示您有多少内存泄漏,并指出分配了泄漏内存的代码行。
2) Point out wrong attempts to free memory(e.g. improper call of delete
)
2)指出释放内存的错误尝试(例如对 的不当调用delete
)
Instructions for using "Valgrind"
“Valgrind”使用说明
1) Get valgrind here.
1)在这里获取 valgrind 。
2) Compile your code with -g
flag
2)用-g
标志编译你的代码
3) In your shell run:
3)在你的shell中运行:
valgrind --leak-check=yes myprog arg1 arg2
Where "myprog" is your compiled program and arg1
, arg2
your programme's arguments.
其中“myprog”是您编译的程序arg1
,arg2
您的程序的参数。
4) The result is a list of calls to malloc
/new
that did not have subsequent calls to free delete.
4) 结果是对malloc
/的调用列表,这些调用new
没有后续的 free delete 调用。
For example:
例如:
==4230== at 0x1B977DD0: malloc (vg_replace_malloc.c:136)
==4230== by 0x804990F: main (example.c:6)
Tells you in which line the malloc
(that was not freed) was called.
告诉您在哪一行malloc
中调用了(未释放的)。
As Pointed out by others, make sure that for every new
/malloc
call, you have a subsequent delete
/free
call.
正如其他人指出的那样,确保对于每个new
/malloc
调用,您都有后续的delete
/free
调用。
回答by Aaron Klotz
- Download Debugging Tools for Windows.
- Use the
gflags
utility to turn on user-mode stack traces. - Use
UMDH
to take multiple snapshots of your program's memory. Take a snapshot before memory gets allocated, and take a second snapshot after a point at which you believe that your program has leaked memory. You might want to add pauses or prompts in your program to give you a chance to runUMDH
and take the snapshots. - Run
UMDH
again, this time in its mode that does a diff between the two snapshots. It will then generate a report containing the call stacks of suspected memory leaks. - Restore your previous
gflags
settings when you're done.
- 下载Windows 调试工具。
- 使用该
gflags
实用程序打开用户模式堆栈跟踪。 - 用
UMDH
把你的程序的内存的多个快照。在分配内存之前拍摄一个快照,并在您认为您的程序已经泄漏内存之后拍摄第二个快照。您可能希望在程序中添加暂停或提示,以便您有机会运行UMDH
并拍摄快照。 UMDH
再次运行,这次是在两个快照之间做差异的模式。然后它将生成一个报告,其中包含可疑内存泄漏的调用堆栈。- 完成后恢复之前的
gflags
设置。
UMDH
will give you more information than the CRT debug heap because it is watching memory allocations across your entire process; it can even tell you if third-party components are leaking.
UMDH
将为您提供比 CRT 调试堆更多的信息,因为它正在监视整个进程中的内存分配;它甚至可以告诉您第三方组件是否泄漏。
回答by LeleDumbo
If you use gcc, there's gprof available.
如果您使用 gcc,则可以使用 gprof。
I wanted to the know how programmer find memory leak
我想知道程序员如何发现内存泄漏
Some uses tools, some does what you do, could also through peer code review
有些使用工具,有些做你做的,也可以通过同行代码
Is there any standard or procedure one should follow to ensure there is no memory leak in the program
是否有任何标准或程序应遵循以确保程序中没有内存泄漏
For me: whenever I create dynamically allocated objects, I always put the freeing code after, then fill the code between. This would be OK if you're sure there won't be exceptions in the code between. Otherwise, I make use of try-finally (I don't use C++ frequently).
对我来说:每当我创建动态分配的对象时,我总是将释放代码放在后面,然后填充它们之间的代码。如果您确定两者之间的代码中没有异常,这将是可以的。否则,我会使用 try-finally(我不经常使用 C++)。
回答by Mankarse
Search your code for occurrences of new
, and make sure that they all occur within a constructor with a matching delete in a destructor. Make sure that this is the only possibly throwing operation in that constructor. A simple way to do this is to wrap all pointers in std::auto_ptr
, or boost::scoped_ptr
(depending on whether or not you need move semantics). For all future code just ensure that every resource is owned by an object that cleans up the resource in its destructor. If you need move semantics then you can upgrade to a compiler that supports r-value references (VS2010 does I believe) and create move constructors. If you don't want to do that then you can use a variety of tricky techniques involving conscientious usage of swap, or try the Boost.Move library.
在您的代码中搜索new
,并确保它们都出现在构造函数中,并且在析构函数中具有匹配的删除。确保这是该构造函数中唯一可能的抛出操作。一个简单的方法是将所有指针包装在std::auto_ptr
, or boost::scoped_ptr
(取决于您是否需要移动语义)。对于所有未来的代码,只需确保每个资源都由在其析构函数中清理资源的对象拥有。如果您需要移动语义,那么您可以升级到支持 r 值引用的编译器(我相信 VS2010)并创建移动构造函数。如果您不想这样做,那么您可以使用各种涉及认真使用交换的棘手技术,或尝试使用 Boost.Move 库。
回答by Benny Tjia
In visual studio, there is a built in detector for memory leak called C Runtime Library. When your program exits after the main function returns, CRT will check the debug heap of your application. if you have any blocks still allocated on the debug heap, then you have memory leak..
This forumdiscusses a few ways to avoid memory leakage in C/C++..
在 Visual Studio 中,有一个内置的内存泄漏检测器,称为 C 运行时库。当你的程序在 main 函数返回后退出时,CRT 将检查你的应用程序的调试堆。如果在调试堆上仍然分配了任何块,则说明存在内存泄漏。
本论坛讨论了几种避免 C/C++ 中内存泄漏的方法。
回答by Divyanshu
You can use the tool Valgrind to detect memory leaks.
您可以使用 Valgrind 工具来检测内存泄漏。
Also, to find the leak in a particular function, use exit(0) at the end of the function and then run it with Valgrind
此外,要查找特定函数中的泄漏,请在函数末尾使用 exit(0),然后使用 Valgrind 运行它
`$` valgrind ./your_CPP_program