2014-04-12 82 views
1

在C/C++中是否有一個函數可以擺脫非動態數據,類似於動態分配內存的函數free();在C++中釋放非動態內存

我嘗試使用功能free(i);但是編譯器報錯:

invalid conversion from 'int' to 'void*' [-fpermissive] 

在下面的代碼我用free(&i);,編譯器沒有報告錯誤,但也並沒有釋放內存。

#include<iostream> 
#include<stdlib.h> 

int main() 
{ 
    int i, n; 
    cin >> n; 
    for(i = 0; i < n; i++); 
    cout << i << endl; 
    free(&i); 
    cout << i << endl; 
    return 0; 
} 

對於輸入15輸出是:

15 
15 

Process returned 0 (0x0) execution time : 11.068 s 
Press any key to continue. 

而且我從編譯器得到了一個警告:

warning: attempt to free a non-heap object 'i' [-Wfree-nonheap-object] 

回答

3

,我會在這裏的情況下,於加初學者水平答案一整套先進的答案實際新手絆倒問題:

你並不需要釋放棧和數據結構 - 正如Deduplicator指出 - 不允許你要麼。除一些特殊情況外,所有未動態分配的數據(例如,通過新的數據)由編譯器置於堆棧上。堆棧是運行時程序的內存部分,隨着每個函數調用而增長,並隨着每個函數出口收縮。它被分成所謂的堆棧幀,它們提供你的函數的本地存儲器。在編譯期間,編譯器會發現函數需要多少內存 - 在你的例子中,對於兩個4字節整數(假設你正在編譯爲一個32位目標)將會是8個字節),並且產生的指令爲所有人創建足夠大的棧幀局部變量駐留在函數被調用時。然而,有一種方式告訴編譯器,你只需要一個變量在函數內部有限的時間內:Scopes,它是由大括號創建的 - 就像niklasfi指出的那樣。舉個例子:

int foo() { 
    int outerScopeVariable = 5; 
    { 
     int innerScopeVariableA = 8; 
    } 
    { 
     int innerScopeVariableB = 20; 
    } 
} 

變量innerScopeVariableA將在它周圍的花括號只「活」。在較高的級別上,這意味着您不能在{}塊以外的作用域中引用它,並且在塊的末尾聲明瞭類的對象的析構函數。在低級別上,編譯器知道在塊末尾爲innerScopeVariableA保留的內存不再需要。因爲它是堆棧內存,儘管它不能像釋放動態內存那樣釋放它。請記住,堆棧內存僅在函數結束時被丟棄。但它可以做的是重用innerScopeVariableA的內存innerScopeVariableB。因此,對於foo,優化編譯器實際上只能使用8個字節的堆棧內存。

有關堆棧和堆的更多信息(這是分配動態內存的地方),您可以看看這個問題:What and where are the stack and heap?。堆棧的更深入的討論可以在這裏找到:http://www.altdevblogaday.com/2011/12/14/c-c-low-level-curriculum-part-3-the-stack/


編輯:如果你把大的數據結構棧上實際上,你可以看到這個堆棧內存重用。運行以下代碼編譯g ++ 4.8.1您的輸出是123987

#include <iostream> 
using namespace std; 

void foo() { 
    { 
     int a[1024]; 
     a[0] = 123987; 
    } 
    { 
     int b[1024]; 
     cout << b[0] << endl; 
    } 
} 

int main() { 
    foo(); 
    return 0; 
} 

尋找在二進制克++儲量4136個字節的堆棧,該堆棧4096的所必需的一個整數數組具有1024種元素於foo(我已經編譯爲一個32位的目標)。多餘的空間可能與內存對齊有關。您也可以通過打印內存地址來觀察這種效果,下面是使用在線編譯器的示例:http://codepad.org/r5S1hvtV

1

您可以直接附上您的代碼在括號{}。任何對象都會駐留在堆棧上,直到周圍的括號關閉。例如。

int b; 
{ 
int a; 
} // a gets destroyed, b is still alive 

由於Deduplicator指出,通常情況下,您不需要照顧變量的銷燬,因爲編譯器會爲您做這件事。

3

始終使用補充分配方法的解除分配方法。
對於堆棧變量,這意味着退出塊,甚至可能是函數。
否則你會得到未定義的行爲,所以一切都可能發生。

在您的例子,free()似乎任

  • 接受堆棧指針和腐敗的棧和堆管理結構,潛在地導致進一步腐敗的路線,
  • 或它檢查是否傳遞的指針可能已經由相應的分配器返回,然後默默無聞。

對於調試,一個嘈雜的崩潰或至少明顯的不當行爲將是可取的,但不能保證。

1

我不會去手動調用析構函數,因爲這是不好的做法,除非對象是使用重載形式的運算符new()構造的,除非使用std::nothrow重載。

一個常見成語擺脫堆棧內存(和technichally資格作爲一個回答你的問題)是有違約互換它構建的臨時

MyType t1; 
std::swap(t1, MyType()); 

第二行交換的實例與暫時的,所以原始實例在該行被破壞。現在

,你還是留在堆棧中的實例,以便有2個情況下,這將有一個意義

  • 你想要的t1析構函數在該行被稱爲(好像擺脫棧對象)
  • 默認的構造類型小得多,所以你要clear and minimize