簡體   English   中英

C ++可變內存分配

[英]C++ Variable Memory Allocation

這些主要是編譯器設計問題。 當您的編譯器編譯它時,例如:

int * pData = new int[256];

如何即時分配內存? 編譯器是否調用為您分配內存的OS例程,或者是一個為您分配內存的函數?

此外,當你寫這樣的東西:

if (x == 5)
    int y;

由於內存不是在運行時分配的,我假設數據占用了程序數據段的一些空間。 由於編譯器無法真正判斷是否為int y; branch將在運行時執行,是為變量保留的內存是否為int y; 執行? 如果它是保留的,那么mem分配塊中可能執行也可能不執行的任何變量的內存效率是否更高?

謝謝

對於第一個問題:當編譯器遇到new運算符時,例如:

int * pData = new int[256];

它有效地發出如下代碼:

int *pData = reinterpret_cast<int*>(::operator new(256 * sizeof(int)));
// the compiler may also choose to reserve extra space here or elsewhere to
// "remember" how many elements were allocated by this new[] so delete[] 
// can properly call all the destructors too!

如果應該調用構造函數,那么也會調用它(在這個例子中,我相信沒有構造函數被調用)。

operator new(std::size_t)是一個由標准庫實現的函數,通常但不總是 ,它將歸結為malloc調用。

malloc必須進行系統調用 ,才能從OS請求內存。 由於OS分配器通常使用較大的固定大小的內存塊,因此malloc不會每次都進行此調用,只有當它已經耗盡了當前的內存時。


對於第二個問題 :對於局部變量,它實際上取決於編譯器。 標准沒有提到堆棧。 但是,很可能您使用的是運行通用操作系統並使用通用編譯器的通用體系結構:-)。

因此,對於共同的情況下,編譯器將通常在函數調用的所有的局部變量的開始通過相應地調節疊層或保留寄存器為它們預留空間,如果它可以(寄存器是優選的選擇,因為它的速度快得多)。

然后(在c ++中),當遇到變量時,它將調用構造函數。 從理論上講,它可以根據需要調整堆棧,但這對於證明正確且效率較低而言將是復雜的。 通常保留堆棧空間是單個指令,因此一次完成所有操作都是非常理想的。

如何即時分配內存? 編譯器是否調用為您分配內存的OS例程,或者是一個為您分配內存的函數?

在大多數實現中,它是這兩者的組合。 通常有一個操作系統服務,用於為進程提供內存塊,還有一些運行時代碼或標准庫中的代碼,用於在應用程序內以更細粒度的規模管理這些內存塊。

是為變量保留的內存,無論是否為“int y;” 執行? 如果它是保留的,那么mem分配塊中可能執行也可能不執行的任何變量的內存效率是否更高?

通常,不 - 只有在執行適當的代碼時才會分配y的空間。 具有自動存儲類的變量通常在堆棧上,因此為它們騰出空間就像修改堆棧指針一樣簡單。 也就是說,在這種情況下,編譯器可以做任何想做的事情,因此檢查工具鏈的輸出是確定的唯一方法。

局部變量(int y)在堆棧上分配。

指針也是如此,但是'new'-ed表達式在堆上分配,通常通過malloc調用。 確切的方法和堆布局是實現定義的。

只有全局靜態數據位於數據段中。

int y的示例將被優化,因為它未被使用。

不同於例如,C#,C ++是不允許減少的范圍為一個變量,以便包裹一個短命的本地在{SomeClass的ÿ; 可以提供幫助,因此它會被破壞

但是,我很確定對於簡單類型(如int)沒有這樣的限制,因為對於那些人永遠不會有這樣的析構函數

關於第二個問題,條件代碼中的變量是一個自動變量。 通常那些是在堆棧上分配的。 在這種情況下,一個好的編譯器會注意到它永遠不會被讀取或寫入,甚至不會為它分配堆棧空間。

這真的取決於第二個例子的編譯器,這就是為什么我們有volatile關鍵字(如果我們將變量映射到更改的地址),或者它可能只是給你一個警告,但我相當肯定它會將它包含在你的程序中(有時你會因為hackish的原因而增加方法的堆棧大小)。 第一個示例本質上調用malloc(256 * sizeof(int))並返回指向該段的指針。

情況1:它將調用OS例程來在堆上分配內存。 操作系統管理內存。

情況2:這是在堆棧上分配的。 堆棧預先分配給您的進程,並用於局部變量和函數參數。

對於第一個問題:

編譯器生成代碼來調用函數operator new ,它本身通常從C運行時庫調用malloc ,它本身調用某個特定於操作系統的庫(你可以看到它的去向),最后切換到內核模式並為進程分配內存。

在任何情況下,編譯器為您自己的程序生成的本機代碼本身不會進行分配。

對於第二個問題:

int y的內存在堆棧上分配。 無論條件是否為真,在最簡單的非優化情況下,每次控制進入函數時都會發生堆棧空間分配。

由於堆棧分配只是幾個寄存器操作,無論分配多少空間都需要相同的時間,並且由於一旦函數返回就會回收內存,因此這里沒有“內存耗盡”問題。

暫無
暫無

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

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