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

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

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

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

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


当前回答

运行“Valgrind”可以:

1)帮助识别内存泄漏-显示您有多少内存泄漏,并指出代码中泄漏内存分配的行。

2)指出错误的释放内存的尝试(例如不正确的delete调用)

“Valgrind”使用说明

1)在这里获得valgrind。

2)使用-g标志编译代码

3)在shell中运行:

valgrind --leak-check=yes myprog arg1 arg2

其中"myprog"是你编译的程序,arg1, arg2是你程序的参数。

4)结果是一个调用malloc/new的列表,没有后续调用free delete。

例如:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)

==4230==    by 0x804990F: main (example.c:6)

告诉您在哪一行(未释放的)调用了malloc。

正如其他人指出的那样,确保对于每个新的/malloc调用,都有一个后续的delete/free调用。

其他回答

在Windows上,你可以使用CRT调试堆。

是否有任何标准或程序可以确保程序中没有内存泄漏。

是的,不要使用手动内存管理(如果你曾经手动调用delete或delete[],那么你做错了)。使用RAII和智能指针,将堆分配限制到绝对最小值(大多数时候,自动变量就足够了)。

有一些著名的编程技术可以帮助您将内存泄漏的风险降至最低:

if you have to do your own dynamic memory allocation, write new and delete 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 of T* 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 not own).

指令

你需要的东西

熟练使用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)。

回答你问题的第二部分,

是否有任何标准或程序可以确保程序中没有内存泄漏。

是的,有。这是C和c++的主要区别之一。

在c++中,永远不要在用户代码中调用new或delete。RAII是一种非常常用的技术,它在很大程度上解决了资源管理问题。程序中的每一个资源(资源是任何需要获取,然后释放的东西:文件句柄,网络套接字,数据库连接,但也包括普通内存分配,在某些情况下,对API调用(BeginX()/EndX(), LockY(), UnlockY()))都应该包装在一个类中,其中:

构造函数获取资源(如果资源是内存分配,则调用new) 析构函数释放资源, 复制和赋值要么被阻止(通过将复制构造函数和赋值操作符设置为私有),要么被实现为正确工作(例如通过克隆底层资源)

然后,该类在本地、堆栈上或作为类成员实例化,而不是通过调用new和存储指针来实例化。

You often don't need to define these classes yourself. The standard library containers behave in this way as well, so that any object stored into a std::vector gets freed when the vector is destroyed. So again, don't store a pointer into the container (which would require you to call new and delete), but rather the object itself (which gives you memory management for free). Likewise, smart pointer classes can be used to easily wrap objects that just have to be allocated with new, and control their lifetimes.

这意味着当对象超出作用域时,它将被自动销毁,并释放和清理它的资源。

如果在整个代码中始终这样做,就不会有任何内存泄漏。所有可能泄露的内容都绑定到析构函数,该析构函数保证在控件离开声明对象的作用域时被调用。

运行“Valgrind”可以:

1)帮助识别内存泄漏-显示您有多少内存泄漏,并指出代码中泄漏内存分配的行。

2)指出错误的释放内存的尝试(例如不正确的delete调用)

“Valgrind”使用说明

1)在这里获得valgrind。

2)使用-g标志编译代码

3)在shell中运行:

valgrind --leak-check=yes myprog arg1 arg2

其中"myprog"是你编译的程序,arg1, arg2是你程序的参数。

4)结果是一个调用malloc/new的列表,没有后续调用free delete。

例如:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)

==4230==    by 0x804990F: main (example.c:6)

告诉您在哪一行(未释放的)调用了malloc。

正如其他人指出的那样,确保对于每个新的/malloc调用,都有一个后续的delete/free调用。