考虑以下代码:
char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1;
delete [] str2;
delete [] str1;
为什么上述程序会导致内存泄漏?我该如何避免这种情况?
答案 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指向的内存块时。所以没有什么可以指向第二个阵列。