2016-11-10 124 views
2

是堆棧或堆場景1中的funcVar?堆棧或堆棧分配不正確

我在問,因爲我懷疑它是,因此這可能是一個很好的方法來做事情,以最大限度地減少內存泄漏。也就是說,最好給東西自動分配位置,然後將代碼放在堆上的較高級別上,這樣可以間接地將事物放在堆上的較低級別,如場景1中所示。

在場景2中,刪除可能永遠不會被調用。通過使用代碼中的場景1,我希望儘量減少(不排除)問題在方案2

方案1

class Test{ 
    int memVar = 1; 

    void func(){ 
     int funcVar = 2; 
     SomeClass::someFuncThatCouldCrash(); 
    } 
}; 

Test* t = new Test(); 

方案2

class Test{ 
    int memVar = 1; 

    void func(){ 
     int* funcVar = new int(2); 
     SomeClass::someFuncThatCouldCrash(); 
     delete funcVar; //May not free due to crash in line above; 
    } 
}; 

Test t; //or Test* t = new Test() 
+0

目前尚不清楚此代碼的意圖。 'funcVar'永遠不會被分配給它的值使用,'someFuncThatCouldCrash'不會修改它。 – Xirema

+0

謝謝,iirc和RyanP,我清理了代碼以便更清楚。 Xirema,這段代碼沒有做有用的事情,我保持精簡,保持清潔並專注於分配和內存清理。 – code

+0

_is funcVar堆棧或堆場景1?_有人會說它既不是堆棧也不是堆,因爲標準沒有提到它們中的任何一個。 – skypjack

回答

1

在方案當調用func()時,1 funcVar(假設它是int funcVar = 2)在堆棧上,並且在方案2中它在堆上。你是對的,如果someFuncThatCouldCrash拋出一個異常,它永遠不會被刪除。

另外,在場景2中,您刪除funcVar,然後將其返回..這不是好事。同樣在那種情況下,當返回類型是一個普通的int時,你返回一個指針。

在C++ 11中,您永遠不想處理raw new和delete。基本上,大多數東西都應該是堆棧上的變量。如果您需要堆分配,請使用類似於向量的東西,該向量是堆棧中的本地變量,用於在內部管理堆分配。這樣,當矢量離開作用域時,它就可以自行清理而不必調用delete。這就是所謂的RAII(資源分配是初始化),如果你想進一步查看它。如果你確實需要一個指向對象的指針(例如通過基類指針持有一個多態對象,或者通常創建大類的實例),那麼你會想要一個std::unique_ptr本質上創建該局部變量負責在您創建的對象上調用delete。在較罕見的情況下,您也可能需要std::shared_ptr,但如果需要,您可以查看所做的事情以及爲什麼需要它。

+0

嗯......所以在場景1中,memVar將在堆上,但funcVar將在堆棧上,這是正確的嗎?我認爲,因爲memVar在場景1中被間接推送到堆中,那麼該函數的「調用堆棧」也會被推送到堆中......但我猜不是。 – code

+0

@code在場景1中,測試't'的實例位於堆上,因此'memvar'(同樣需要一個類型)將成爲堆上該對象的一部分。當你調用func()時,它會成爲調用堆棧中的一個函數,並且它的所有局部變量(包括'funcVar')都是該堆棧幀的一部分。 – RyanP

+0

我明白了。那麼你會說如果沒有使用std :: unique_ptr或std :: shared_ptr,那麼真的沒有切換器方法逃避內存泄漏嗎? – code

0

在第一種情況下,它在堆棧上分配。在第二種情況下,它被分配到堆上,並且如果從SomeClass::someFuncThatCouldCrash中拋出的異常被進一步捕獲,則它是正確的。

如果要保持內存安全但使用動態分配,則應根據使用情況使用std::unique_ptrstd::shared_ptr

0

自動存儲中的局部變量位於「堆棧」上。

類成員變量位於「堆棧」或「堆」上,具體取決於類的實例是在「堆棧」還是「堆」上。

全局數據(包括靜態局部變量和靜態類成員變量)既不在「堆棧」也不在「堆」中。

線程本地數據既不是「堆棧」也不是「堆」(但它可能在堆上實現)。

所以場景1具有funcVar作爲局部變量,因此對「棧」。類Test的實例在堆上。

在場景2中,funcVar保留在「堆棧」上,但它指向是「堆」上的內容。它確實不是特例安全的;如果拋出異常,它可能會泄漏。幾乎任何操作系統上都會發生崩潰,清理任何「剩餘」的簡單內存資源。在某些情況下,有時可能會有一些資源在過程退出時不能回收,但它們不是mallocnew返回的資源。

使用std::unique_ptrstd::make_unique減輕幾乎所有的這種泄漏。在現代C++中,避免在類型系統中沒有明確擁有的原始指針分配和內存資源通常被認爲是一個好主意。