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

C++ 为什么这个C++;程序导致内存泄漏?,c++,memory,memory-leaks,C++,Memory,Memory Leaks,考虑以下代码: char* str1 = new char [30]; char* str2 = new char [40]; strcpy(str1, "Memory leak"); str2 = str1; delete [] str2; delete [] str1; 为什么上面的程序会导致内存泄漏?如何避免这种情况?因为您将删除str1(它指向的内存)两次,并且不会删除在str2第一次指向的位置下分配的内存 编辑: 我不知道你想达到什么目

考虑以下代码:

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

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

delete [] str2;     
delete [] str1; 

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

因为您将删除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。

您将str1指针分配给str2指针,因此删除[]str1并删除[]str2仅释放str1指向的内存(str2指向同一内存)。您需要在释放指向它的指针之前释放str2内存(在将str1分配给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; 

内存中的每个对象都需要指向

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

因此,在您的情况下,您将丢失第二个数组在内存中的位置。因此,内存中有一个数组丢失了,您无法访问


当你做
str2=str1str2现在指向str1指向的内存块。因此,没有任何东西可以指向第二个数组。

上述情况不仅会导致内存泄漏;它会导致未定义的行为,这是非常非常糟糕的

问题出现在最后三行:

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

现在,不需要显式管理内存,也不必担心缓冲区溢出或双重释放。对象内存分配的魔力拯救了您。

使指针成为常量指针


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

这是家庭作业吗?如果是,应该这样标记。您可以使用
std::vector
std::string
来避免它。将
str2=str1
替换为
strcpy(str2,str1)
@MichaelKjörling:为什么?我想你是对的,我无法想象除了C或C++的记忆管理之外,有谁曾经被其他人迷惑过。“千里眼”有没有额外的选票;-)@Filip Ekberg:添加了更多的解释,尽管我不确定OP想要实现什么。常量指针将节省调试时间并在编译时显示错误,IMHOIt总是很高兴在其中获得更多的信息。如果OP以外的其他人想知道类似的事情,最好有一些例子。:)编辑得不错。这仍然会泄漏,因为
char*str2=newchar[40]
可能抛出,导致str1永远不会被释放。
+1
这是迄今为止唯一一个说明应该如何做这类事情的答案:使用一个封装资源的类。