为什么这个C++程序会导致内存泄漏?

mr_*_*air 5 c++ memory memory-leaks

考虑以下代码:

char* str1 = new char [30];    
char* str2 = new char [40];   

strcpy(str1, "Memory leak");    
str2 = str1;     

delete [] str2;     
delete [] str1; 
Run Code Online (Sandbox Code Playgroud)

为什么上述程序会导致内存泄漏?我该如何避免这种情况?

tem*_*def 21

以上不仅会导致内存泄漏; 它导致未定义的行为,这更糟糕.

问题出在最后三行:

str2 = str1; 
delete [] str2; 
delete [] str1; 
Run Code Online (Sandbox Code Playgroud)

如果我们忽略第一行,那么最后两行正确地回收了此函数中分配的所有内存.但是,第一行设置str2为指向相同的缓冲区str1.由于它str2是程序中唯一指向它引用的动态内存的指针,因此该行会泄漏该缓冲区的内存.更糟糕的是,当你执行接下来的两行来清理两个指针时,你会删除相同的内存块两次,一次通过str2,一次通过str1.这会导致未定义的行为并经常导致崩溃.特别是恶意用户实际上可以使用它来执行程序中的任意代码,所以小心不要这样做!

但是这里有一个更高级别的问题需要考虑.此设置的整个问题是您必须执行所有自己的内存管理.如果您选择使用std::string而不是原始C风格的字符串,那么您可以编写如下代码:

string str1 = "Memory leak"; // Actually, it doesn't. :-)
string str2;

str2 = str1; // Okay, make str2 a copy of str1

// All memory reclaimed when this function or block ends
Run Code Online (Sandbox Code Playgroud)

现在,没有必要显式管理内存,您不必担心缓冲区溢出或双重释放.你被对象内存分配的魔力所拯救.

  • `+ 1`是唯一的答案(到目前为止),显示你应该如何做这种事情:通过使用包装资源的类. (5认同)

Ste*_*fan 20

因为您正在删除两次str1(它指向的内存)并且您不删除在str2首先指向的位置下分配的内存.

编辑:我不确定你想要实现的目标.

char* str1 = new char [30];
// str1 = 0x00c06810; (i.e.)
char* str2 = new char [40];
// str2 = 0x00d12340; (i.e.)
strcpy(str1, "Memory leak");

// delete [] str2; should be here

str2 = str1; 
// now str2 == str1, so str2 = 0x00c06810 and str1 = 0x00c06810
// deleting 0x00c06810
delete [] str2; 
// deleting 0x00c06810 once again
delete [] str1;
// 0x00d12340 not deleted - memory leak
Run Code Online (Sandbox Code Playgroud)

如果你想要那个赋值(str2 = str1),那么首先删除str2.