函式棧區分析

2021-07-15 02:55:56 字數 2264 閱讀 7507

最近因為函式中訪問陣列越界導致段錯誤,於是對函式棧進行了分析,得出一些結論: 1,

函式區域性變數棧位址是執行時才分配的,函式呼叫返回後分配的站空間被**重複利用 2,

程式中所有函式共用一段棧空間,可以把它稱為執行緒棧空間——執行緒棧起始位址及棧大小,被調的函式執行過程不斷在這段棧空間進行進棧出棧,某段位址可能會被重複使用多次。 3,

區域性變數陣列訪問越界並不一定會導致段錯誤,越界訪問肯定產生記憶體棧區內容覆蓋,覆蓋的是關鍵資料時會導致異常,比如函式返回位址被覆蓋,此時pc指標指向了未知區域而導致段錯誤。 4,

函式棧分配原則先給本函式分配棧區,執行到呼叫的子函式時再給子函式分配棧區,棧區分配起始位址緊接上次分配的最後位址。 5,

如果函式中有條件語句,例如:

if(ret == 0) ;

}else ;

}則會給此函式分配條件語句中佔空間最大的一段區間,即分配200個位元組,如果ret是0,則a會占用200個位元組棧區空間,如果將s8 a[100] = ; 這條語句去掉,還會占用200位元組棧區空間。

現對於上面所述進行部分驗證:

**:

void get_info(s8 *info)

void indirect_call(void) ;

get_info(a);

printf("@[%s] a addr:%u a:%s\n", __function__, (u32)a, a); }

int main(void) ;

get_info(a);

printf("@[%s] a addr:%u a:%s\n", __function__, (u32)a, a);

indirect_call();

s8 b[10] = ;

printf("@[%s] b addr:%u\n", __function__, (u32)b);

return 0; }

描述:直接呼叫get_info與間接呼叫get_info函式檢視區域性變數位址變化情況。

執行:@[get_info] msg addr:3215719804

@[main] a addr:3215719860 a:hello

@[get_info] msg addr:3215719756

@[indirect_call] a addr:3215719796 a:hello

@[main] b addr:3215719850

從執行的結果可以看出,進入main函式時,區域性變數a,b就被分配了棧空間,通過訪問區域性變數通過棧指標、函式棧起始位址及偏移量實現的,這個可以反彙編得出結論,在此省略。程式執行到呼叫get_info函式時,又產生了一次棧空間分配,記憶體分布如下:

棧位址增長方向由高到低的,陣列a位址為3215719860,占用8個位元組,接著是陣列b的位址3215719850,剛好偏移10個位元組是陣列b的大小,中間一段空白區是儲存呼叫get_info函式時相關資訊,比如狀態暫存器,返回位址,臨時變數等。接著是get_info函式中指標變數msg位址,呼叫get_info函式完成後3215719804—3215719850這段棧空間被釋放。

程式執行到呼叫indirect_call函式時,站空間又從起始位址3215719850分配一段位址給indirect_call函式,我們可以看到此函式裡面陣列a的位址為3215719796,占用8個位元組一直到321579804,接著又呼叫了一次get_info函式,此時指標msg位址變為了321579756,棧位址分布如下:

至此,我們可以得到兩個資訊:1,函式棧空間在執行時分配的,兩次呼叫get_info,指標變數msg位址不一樣;2,321719850往下棧位址被分配使用**後又再一次被分配使用;3,陣列b的位址比msg位址大,說明b的位址分配先於呼叫get_info函式,雖然b的定義在呼叫get_info函式之後。

棧的分析(一) 函式呼叫棧

當發生函式呼叫的時候,棧空間中存放的資料是這樣的 1 呼叫者函式把被調函式所需要的引數按照與被調函式的形參順序相反的順序壓入棧中,即 從右向左依次把被調函式所需要的引數壓入棧 2 呼叫者函式使用call指令呼叫被調函式,並把call指令的下一條指令的位址當成返回位址壓入棧中 這個壓棧操作隱含在cal...

min函式棧解題思路分析

劍指offer面試題21 目的 為快速得到min,需要儲存min 維持題目條件的完整性 棧,其性質 出棧 入棧 出棧 入棧對min帶來的影響 min會變化。出棧 min沒出,min不變 min出了,新的min是?這裡的誤區 min出了,新的min是第二小元素。錯誤,因為min出了,min可能不變,棧...

核心延遲函式分析,區分delay和sleep

linux核心提供3個函式分別進行納秒,微妙和毫秒延時 void ndelay unsigned long nsecs void udelay unsigned long usecs void mdelay unsigned long msecs 這3個函式的延時原理是忙等待,也就是說在延時的過程中...