我試圖理解堆疊和幀指標。我有下面的簡單 C 程式:
#include <stdio.h>
#include <stdlib.h>
int myfunction(int counter) {
int result = 5;
printf("myfunction %p %p %p\n", &result, &counter, __builtin_frame_address(0));
return 0;
}
int main()
{
int i;
int j;
printf("main %p %p\n", &i, __builtin_frame_address(0));
myfunction(4);
return 0;
}
當我使用 gdb 運行程式并檢查以內置框架地址開始的記憶體位置時,我得到以下輸出:

這引起了我的困惑。我假設具有地址的 FP0xbffff608將指向堆疊的起始地址,因此我預期result并且counter記憶體地址開始高于或低于 FP 地址,但這是不遵循的記憶體地址的順序我的假設,有人可以幫忙澄清一下嗎?
記憶體地址:
- 0xbffff608(內置幀地址,我假設這是幀指標)
- 0xbffff610(計數器引數的地址)
- 0xbffff5f8(結果變數的地址)
讓我困惑的是,我認為幀指標表示堆疊的起始地址,因此在這種情況下 0xbffff608 指向當前堆疊的起始地址,那么當前堆疊中的計數器和結果應該都在幀指標之后或之前開始. 但是,現在它是混合的。counter 的記憶體地址高于幀指標,而 result 的記憶體地址低于幀指標。如果幀指標指示堆疊的開始,為什么會出現這種情況?
更新:主函式反匯編

uj5u.com熱心網友回復:
幀指標的確切使用取決于系統和編譯器,但觀察結果可以解釋如下:
之間的差counter和result是counter是由呼叫方(壓入堆疊的引數main()),而result是嚴格屬于功能(一個區域變數myfunction())。
只result屬于函式框架,因為函式只負責清理自己的區域變數,而引數由呼叫者清理。
呼叫者負責清理引數是很有意義的,因為引數的大小可能不是恒定的(例如printf())。
uj5u.com熱心網友回復:
堆疊的順序是
- 引數
- 退貨地址
- 基指標
- 區域變數
在 < 11> 處,您可以看到 ebp = esp 對 myFunction 也會發生同樣的情況。如果您查看順序,您會注意到引數具有更高的地址。這就是為什么計數器的地址更高而結果更低的原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/361011.html
