我是Windows平台上的c++程序员。我使用的是Visual Studio 2008。

我通常会在代码中出现内存泄漏。

通常我通过检查代码来发现内存泄漏,但这很麻烦,而且并不总是一种好方法。

因为我买不起付费的内存泄漏检测工具,所以我想让你们建议避免内存泄漏的最佳方法。

我想知道如何程序员可以找到内存泄漏。 是否应该遵循某种标准或过程来确保程序中没有内存泄漏?


当前回答

如果使用gcc,则有gprof可用。

我想知道程序员如何发现内存泄漏

有些人使用工具,有些人做你做的事情,也可以通过同行代码审查

是否应该遵循某种标准或过程来确保程序中没有内存泄漏

对我来说:每当我创建动态分配对象时,我总是把释放代码放在后面,然后在中间填充代码。如果您确定之间的代码中不会出现异常,那么这样做是可以的。否则,我会使用try-finally(我不经常使用c++)。

其他回答

指令

你需要的东西

熟练使用c++ c++编译器 调试器和其他调查软件工具

1

理解操作符的基础知识。c++操作符new分配堆内存。delete操作符释放堆内存。对于每一个new,你应该使用delete来释放你分配的内存:

char* str = new char [30]; // Allocate 30 bytes to house a string.

delete [] str; // Clear those 30 bytes and make str point nowhere.

2

仅在删除时重新分配内存。在下面的代码中,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

注意那些指针的赋值。每个动态变量(在堆上分配内存)都需要与一个指针相关联。当一个动态变量与其指针分离时,它就不可能被删除。同样,这会导致内存泄漏:

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

小心使用局部指针。在函数中声明的指针分配在堆栈上,但它所指向的动态变量分配在堆上。如果你不删除它,它将在程序退出函数后继续存在:

void Leak(int x){

char* p = new char [x];

// delete [] p; // Remove the first comment marking to correct.

}

5

注意“delete”后面的方括号。使用delete本身来释放单个对象。使用带方括号的delete[]来释放堆数组。不要做这样的事情:

char* one = new char;

delete [] one; // Wrong

char* many = new char [30];

delete many; // Wrong!

6

如果泄漏还允许-我通常寻求它与deleaker(检查这里:http://deleaker.com)。

确保成功释放了所有堆内存。如果您从未在堆上分配内存,则不需要这样做。如果你这样做,计算你malloc内存的次数,并计算你释放内存的次数。

您可以在代码中使用一些技术来检测内存泄漏。最常见和最简单的检测方法是,定义一个宏(比如DEBUG_NEW),并使用它与预定义的宏(如__FILE__和__LINE__)一起定位代码中的内存泄漏。这些预定义的宏告诉您内存泄漏的文件号和行号。

DEBUG_NEW只是一个宏,通常定义为:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

因此,无论在哪里使用new,它都可以跟踪文件和行号,这可以用来定位程序中的内存泄漏。

而__FILE__, __LINE__是预定义的宏,它们分别计算你使用它们的文件名和行号!

阅读下面的文章,它解释了使用DEBUG_NEW和其他有趣的宏的技术,非常漂亮:

一个跨平台的内存泄漏检测器


从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.

如果使用gcc,则有gprof可用。

我想知道程序员如何发现内存泄漏

有些人使用工具,有些人做你做的事情,也可以通过同行代码审查

是否应该遵循某种标准或过程来确保程序中没有内存泄漏

对我来说:每当我创建动态分配对象时,我总是把释放代码放在后面,然后在中间填充代码。如果您确定之间的代码中不会出现异常,那么这样做是可以的。否则,我会使用try-finally(我不经常使用c++)。

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 run UMDH 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.

UMDH会给你比CRT调试堆更多的信息,因为它会监视整个进程的内存分配;它甚至可以告诉您第三方组件是否泄漏。