簡體   English   中英

堆棧上的內存泄漏

[英]Memory leak on the stack

通過非常糟糕的設計,是否有可能在沒有堆分配的情況下在C ++中創建內存泄漏?

我想到的一個例子,請糾正我,如果它沒有做我認為它做的事情:

#include <iostream>
#include <string>

void WhatIsYourName()
{
  std::string name;
  std::cout << "What is your name? ";
  getline (std::cin, name);
  std::cout << "Hello, " << name << "!\n";

  WhatIsYourName();
}

int main()
{
  WhatIsYourName();
}

對我來說,看起來WhatIsYourName()在每次調用時都在初始化一個新的std::string name ,但該函數從未真正超出范圍,因此永遠不會釋放內存。 那正確嗎 ? 或者編譯器是否足夠智能以確定將來不會使用該變量,因此如果函數超出范圍 ,它會刪除它?

什么樣的其他糟糕的設計只使用堆棧分配會造成內存泄漏?

你有一個不停止的遞歸調用(沒有退出條件),所以為每個函數調用創建一個新的堆棧頁面,直到程序因堆棧溢出而崩潰。 編譯器無法優化它。

關於你的上一個問題,是否有可能在沒有堆分配的情況下創建內存泄漏(並且沒有這種無限遞歸),我相信不是,局部變量會自動釋放,這就是為什么這種類型的存儲持續時間稱為自動存儲持續時間

不可能使用具有自動存儲持續時間的對象(有些人稱之為此堆棧)創建內存泄漏。 當您有一個具有自動存儲持續時間的變量時,程序會自動清理它。 一旦范圍結束,它被聲明在它中被銷毀並且它所擁有的任何資源被釋放(只要它被正確設計)。 在您的示例中,即使您由於無限遞歸而從未退出作用域,也不是內存泄漏。 如果無限遞歸被刪除,而是在某種情況下結束,那么你聲明的所有變量都將被清除。

要獲得內存泄漏,您需要創建一個具有動態存儲持續時間的對象(有些人稱之為堆)並且從不清理它。 當您擁有具有動態存儲持續時間的對象時,編譯器不會為您清理它。 你需要確保自己清理它。 這是忘記或遺漏清理代碼導致內存泄漏。

問題比你想象的更有趣。 根據定義沒有內存泄漏,因為只有當a)指向已分配內存的指針丟失時(這里不是這種情況)或b)在程序正常退出之前,指針永遠不會被釋放,因此只能發生內存泄漏。 第二種情況也不是這樣,因為這個程序永遠不會正常退出。

但是,有一個有趣的問題是字符串變量實際發生了什么。 由於遞歸調用發生在函數的末尾,所以看起來代碼似乎是尾調​​用優化的候選者。 但是,如果檢查程序集,則不會發生,因為編譯器需要在從尾調用返回后調用字符串析構函數。 我個人認為這是優化中的一個缺陷,因為潛在的編譯器應該能夠看到在調用之后不使用字符串變量並提前破壞它。

我認為你誤解了C和C ++世界中的內存泄漏。 鑒於您的條件“沒有堆分配”,它不可能泄漏內存。

內存泄漏通常與動態內存分配相關聯,然后失去解除分配的能力。 例如:

// Memory leak
int x;
int *q = new int;
q = &x; // memory leak because the "allocated" q is lost.

使用RAII而不使用new + delete進行內存管理,在C ++中很容易避免。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM