2014-02-13 78 views
0

最近我發佈了一個問題:"Do functions occupy memory space?"
最好的答案,我得到的是:函數中佔用內存空間的是什麼?

是,該功能佔用內存空間,但是它的大小完全取決於功能。

現在我不問他們佔用的確切數量,但是函數中佔用內存空間的是什麼?

爲〔實施例: -

​​

上述功能編譯沒有任何錯誤,但這個功能完全是空的,它是不是有連return聲明。那麼,佔用這個功能的內存空間是什麼?

+2

一個好的編譯器應該優化和刪除這個函數,即使你調用它。但是假設如果你打印deom的地址,那麼函數定義將存在於可執行文件中。 –

回答

4

編輯:謝謝Pascal他的評論這確實是正確的!因此,我已經改變了答案。


使用任何優化設置比沒有其他,編譯器會優化該函數遠離,如果它是靜態定義即本地到此編譯單元。沒有優化打開它可能不會。在這種情況下,function prologue and epilogue,它們是在進入函數時設置堆棧幀等並在離開時破壞它的代碼,可能仍會由編譯器發出。

由於Pascal指出,當它有外部鏈接時,這是不可能的,因爲編譯器通常不會跨越模塊「達到」。但是,在這種情況下,如果鏈接器檢測到該函數未被調用,則應該優化它。

此外,完全可以確定函數佔用了多少內存。你可以看一下elfdump/objdump或類似的適當的工具,用於包含函數:)


要回答你的問題

如果函數被調用的對象,那麼什麼是佔用內存空間?

函數必須被編譯成machine code。這是一組駐留在內存中的與體系結構有關的長度/值等的指令。計算機從內存中獲取指令。因此,您的函數必須駐留在內存中的某處,以便CPU能夠獲取並執行它。你寫的C代碼被編譯到這個機器代碼中,這就佔用了內存空間...

+3

「使用除none以外的任何優化設置,編譯器應該優化此功能」絕對不是。一個函數'demo'具有外部鏈接。它不能被編譯器刪除。 –

+0

是非常好的一點,謝謝大家指出,+1 – Jimbo

+0

@Jimbo:如果函數被調用,那麼佔用內存空間是什麼? –

1

編譯器通常會在優化時跳過這個函數。所以答案是沒有內存將保留調用一個空函數。

1

如果我們忽略編譯器可能會或可能不會優化功能,那麼函數佔用的內存有很多種。

每次調用某個函數時,程序都可能需要將各種CPU寄存器存儲在堆棧中,例如status/condition code register等寄存器。此外,程序計數器將被存儲在堆棧中,或者一旦該函數完成執行,CPU就不知道該返回到哪裏。

什麼樣的寄存器被保存,以及在哪裏以及如何取決於系統。在程序中遇到「執行功能」指令時,CPU可能會自動執行很多操作。

如果有任何參數或返回值,它們也將被存儲在堆棧/寄存器中。在這種情況下,它們可以由呼叫者或功能保存,它是系統特定的並且被稱爲calling convention

除上述之外,作爲函數主體的實際代碼當然也存儲在某處:程序存儲器中(通常稱爲.text)。

1

讓我們假設編譯器不會省略給定的函數,因爲它什麼都不做。並且假定編譯器不會內聯它,因爲函數很小。你的斷言函數不做任何事情,不調用另一個函數,沒有局部變量,也沒有參數和返回值 - 那爲什麼需要任何內存?

第一件事,函數佔用的大小將在兩個位置。一個是生成的二進制文件(可執行文件),另一個是調用該函數的線程的調用堆棧。一個空函數有點像零字節文件或目錄。 看似不佔用磁盤中的任何存儲(因爲它顯示爲'0字節')。但是,他們需要一些內存是磁盤。

空文件的類比與空函數不完全相同,只是爲了理解目的,我寫了。函數會被某個函數(調用者)調用,因此該函數的返回地址將被保存在當前線程的調用堆棧中。當函數停止存在時,將返回該地址,並且ESP將指向下一條指令的該位置。

調用約定也會爲空函數添加更多指令來清理調用堆棧。例如,Pascal調用約定在函數退出時會有更多的指令來清理調用堆棧。

程序的位數(32位或64位)也會改變所有簿記所需的大小。

相關問題