【问题标题】:Why does this C++ program cause a memory leak?为什么这个 C++ 程序会导致内存泄漏?
【发布时间】:2011-06-25 10:41:35
【问题描述】:

考虑以下代码:

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

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

delete [] str2;     
delete [] str1; 

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

【问题讨论】:

  • 这是作业吗?如果是,它应该被标记为这样。
  • 您可以通过使用std::vector<char>std::string 来避免它。
  • strcpy(str2, str1)替换str2 = str1
  • @MichaelKjörling:为什么?我想你是对的,我无法想象除了学生之外的任何人都曾被 C 或 C++ 中的内存管理所迷惑。

标签: c++ memory memory-leaks


【解决方案1】:

上述情况不仅会导致内存泄漏;它会导致未定义的行为,这要糟糕得多。

问题出在最后三行:

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 唯一的答案(到目前为止)显示你应该如何做这种事情:通过使用包装资源的类。
【解决方案2】:

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

【讨论】:

  • @Filip Ekberg:添加了更多解释,但我不确定 OP 想要实现什么。
  • const 指针将节省调试时间并在编译时显示错误,恕我直言
  • 在那里获得更多信息总是很好的。如果OP以外的其他人想知道类似的东西,最好有一些例子。 :) 不错的编辑。
  • 这仍然会泄漏,因为char* str2 = new char [40]; 可能会抛出,导致 str1 永远不会被释放。
【解决方案3】:

您将 str1 指针分配给 str2 指针,因此 delete[]str1 和 delete[]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; 

【讨论】:

  • 在我回答的时候,问题中没有 new() 。你有额外的千里眼投票吗;-)
【解决方案4】:

将指针设为 const 指针

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

【讨论】:

    【解决方案5】:

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

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

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

    当您执行 str2 = str1; 时,str2 现在指向 str1 指向的内存块。所以没有什么可以指向第二个数组了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多