2011-06-20 165 views
0

我有一個關於我的C++代碼中的內存管理的一般問題。編譯器抱怨說,當我用一個指向我已經在堆棧上動態初始化的對象的新指針替換指向對象的指針時,存在潛在的內存泄漏。例如:C++指針和堆棧內存管理

int* foo(int* h){ 
int* b = new int(5); 
b = h; //Memory leak here. How do I delete b without creating a dangling pointer? 
return b; 
} 

然後我用這個功能來改變指針

int i = 1; int* c = &i; foo(c);

的狀態所以我的問題是我有一個具有類似於上面的一個函數的類。 什麼時候可以從foo函數中刪除b?

delete b; 

將這個進入析構函數(這不會幫助我,因爲我使用的時間函數foo的負荷。因此堆將得到可能使用起來....?)

如果我上面沒有提供足夠的信息。請告訴我。

+2

讓我們從基礎開始:你的函數'foo'不修改值由它的參數指向的。它應該做什麼? – Jon

+0

'foo(c);'不要做任何事'c' – rmflow

+0

老實說,我不明白你的問題..但存在內存泄漏的風險,例如:foo(new int);這裏int會在你調用foo時泄漏 –

回答

2

由於這是一個普遍的問題,我首選的一般方法是使用智能指針,在你的班級中使用RAII進行處理。

智能指針封裝了原始指針,併爲您處理所需的內存管理 - 當您的類被破壞時,無論指針值在哪裏被保存,都將被清除而不必手動刪除它。當您爲智能指針分配一個新值時,它會自動刪除您的現有值(如果有的話)。

boost::scoped_ptr作爲班級成員應該在這裏適合你。

這裏似乎也有困惑,關於什麼是在堆棧上和什麼是在堆上。您不會因爲您一遍又一遍地調用foo(除非遞歸到foo無界,在這種情況下最終會用完堆棧空間)而用完堆棧。您的本地變量b位於堆棧上,但它指向在堆上使用new分配的內存。當您退出foo時,堆棧將重置爲調用功能 - 用於b的堆棧內存現在可用於其調用的下一個功能 - 但仍需要保留b指向的堆內存的所有權(並最終釋放)。

編輯:一些示例代碼應該澄清的智能指針的方法

class MyClass { 
public: 
    MyClass() {} // no explicit init for myPointer needed 
    ~MyClass() {} // frees up any pointer held in myPointer, no explicit delete needed 

    void Foo(int* c) 
    { 
    myPointer.reset(c); // releases any existing value, takes ownership of c 
    } 

private: 
    boost::scoped_ptr<int> myPointer; // initially empty 
}; 
+0

嗨史蒂夫。最後一段是我問的問題。只是從來沒有制定過它。我怎樣才能從堆中釋放內存而不會成爲懸掛指針?或者這不會發生?再次感謝! – MWright

+0

我已經添加了一些代碼來澄清,希望這有助於。智能指針和RAII是提高C++生產力和代碼質量的關鍵部分。理解封面下面發生的事情很重要,以及如何在原始問題中手動使用'new/delete'來完成。 –

+0

謝謝史蒂夫,這太棒了!提升是STL的一部分還是我需要一個庫?這是非常C#ish – MWright

3

如果你真的想在函數分配一個新的指針來代替指針的值,我會建議使用一個參考:

void SomeClass::foo(int*& h) 
{ 
    delete h; 
    h = new int(5); 
} 

當然,如果你有一個指針調用它,這將打破一個int這是不是在堆上,因爲你不能delete它在那種情況下。所以不要這樣做。

+0

嗨放鬆。我改變了我的功能?刪除b在哪裏?在函數中設置h之後還是會導致h成爲懸掛指針? – MWright