堆疊損壞

堆疊是一種數據項按序排列的數據結構,只能在棧頂對數據項進行插入和刪除,堆疊損壞便是這種數據結構的損壞。

概念簡介

1.棧(Stack)是作業系統在建立某個進程時或者執行緒(在支持多執行緒的作業系統中是執行緒)為這個執行緒建立的存儲區域,該區域具有FIFO的特性,在編譯的時候可以指定需要的Stack的大小。在編程中,例如C/C++中,所有的局部變數都是從棧中分配記憶體空間,實際上也不是什麼分配,只是從棧頂向上用就行,在退出函式的時候,只是修改棧指針就可以把棧中的內容銷毀,所以速度最快。

2.堆(Heap)是應用程式在運行的時候請求作業系統分配給自己記憶體,一般是申請/給予的過程,C/C++分別用malloc/New請求分配Heap,用free/delete銷毀記憶體。由於從作業系統管理的記憶體分配所以在分配和銷毀時都要占用時間,所以用堆的效率低的多!但是堆的好處是可以做的很大,C/C++對分配的Heap是不初始化的。

堆疊幀的銷毀

當函式將返回值賦予某些暫存器或者拷貝到堆疊的某個地方後,函式開始清理堆疊幀,準備退出。堆疊幀的清理順序和堆疊建立的順序剛好相反:

1)如果有對象存儲在堆疊幀中,對象的析構函式會被函式調用。

2)從堆疊中彈出先前的通用暫存器的值,恢復通用暫存器。

3)ESP加上某個值,回收局部變數的地址空間(加上的值和堆疊幀建立時分配給局部變數的地址大小相同)。

4)從堆疊中彈出先前的EBP暫存器的值,恢復EBP暫存器。

5)從堆疊中彈出函式的返回地址,準備跳轉到函式的返回地址處繼續執行。

6)ESP加上某個值,回收所有的參數地址。

常用的調用約定

1) __cdecl。這是VC編譯器默認的調用約定。其規則是:參數從右向左壓入堆疊,函式退出時由caller清理堆疊中的參數。這種調用約定的特點是支持可變數量的參數,比如printf方法。由於callee不知道caller到底將多少參數壓入堆疊,因此callee就沒有辦法自己清理堆疊,所以只有函式退出之後,由caller清理堆疊,因為caller總是知道自己傳入了多少參數。

2) __stdcall。所有的Windows API都使用__stdcall。其規則是:參數從右向左壓入堆疊,函式退出時由callee自己清理堆疊中的參數。由於參數是由callee自己清理的,所以__stdcall不支持可變數量的參數。

3) __thiscall。類成員函式默認使用的調用約定。其規則是:參數從右向左壓入堆疊,x86構架下this指針通過ECX暫存器傳遞,函式退出時由callee清理堆疊中的參數,x86構架下this指針通過ECX暫存器傳遞。同樣不支持可變數量的參數。如果顯式地把類成員函式聲明為使用__cdecl或者__stdcall,那么,將採用__cdecl或者__stdcall的規則來壓棧和出棧,而this指針將作為函式的第一個參數最後壓入堆疊,而不是使用ECX暫存器來傳遞了。

相關詞條

熱門詞條

聯絡我們