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

时间:2011-02-11 09:35:43

标签: c++ memory memory-leaks

考虑以下代码:

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

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

delete [] str2;     
delete [] str1; 

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

5 个答案:

答案 0 :(得分:21)

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

问题在于最后三行:

str2 = str1; 
delete [] str2; 
delete [] str1; 

如果忽略第一行,则最后两行正确回收此函数中分配的所有内存。但是,第一行将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

现在,没有必要明确管理内存,您不必担心缓冲区溢出或双重释放。通过对象内存分配的魔力来保存你。

答案 1 :(得分: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

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

答案 2 :(得分:4)

将str1指针指定给str2指针,因此删除[] str1并删除[] str2只释放str1指向的内存(str2指向同一个内存)。在丢失指向它的指针之前(在将str1指定给str2之前)需要释放str2内存

正确的方法是

char* str1 = new char [30];

char* str2 = new char [40]; //or just don't allocate this if You don;t need it

strcpy(str1, "Memory leak");

**delete [] str2;** 

str2 = str1; 


delete [] str1; 

答案 3 :(得分:2)

指出是const指针

问题是您为两个数组分配内存,得到两个指针,然后用第一个数组的地址覆盖第二个数组的地址。所以你试着释放第一个数组的内存

答案 4 :(得分:0)

每个对象都需要指向内存。

指针跟踪数据的位置(请记住,与小数组相比,RAM内存是巨大的。)

所以在你的情况下,你正在丢失第二个数组在内存中的位置。所以在内存中有一个阵列丢失了,你无法到达。

当你执行str2 = str1; str2指向str1指向的内存块时。所以没有什么可以指向第二个阵列。