一段簡單程式引發的棧故事

2021-05-09 16:17:31 字數 1343 閱讀 9929

先看下面一段程式:

初步看,test這個函式很不和諧,p是個區域性變數,而返回值也是它,函式返回時它的空間就不復存在了。可當你寫**寫得暈頭轉向的時候,轉念一想,p也是個常量指標,"hello world!"這個串並不儲存在棧區,而儲存於常量區呀,即使棧的內容消失了,返回指向常量區的乙個指標也不會有什麼問題。

那就試試吧。

在15行 printf(str)處設定斷點,debug,執行到斷點處的時候,發現str指向確實是"hello world!"串,而且n的值也是12,心中竊喜!繼續單步執行,列印出來的結果卻不是原來str中的串,變成了"hell??"只有前面4個位元組還在,後面的內容全沒了,而且str中的內容也是這個"hell??"了,難道在printf中有什麼秘密?

於是再手工打造乙個簡單字串拷貝函式,程式改寫成下:

繼續除錯,發現執行完copystr後,str中的內容變成了「燙燙燙」,看來不是printf引起的問題,肯定是在呼叫copystr的時候,修改了str所指的內容。

究竟是什麼修改了str,難道常量區的內容被莫名修改??

回到堆疊的問題上來,我們可以在除錯中看各種變數的位址及記憶體中的資訊。

繼續看第一段**,在test函式的第一行設定斷點,執行到此的時候檢視p的值,發現是0x0012fedc,開啟記憶體檢視器,找到0x0012fedc處,發現附近值全為cc,單步執行一次,此處的值變為了"hello world!"。可見p在被初始化的時候,是從某個地方把"hello world!"搬移到p所在的位址的,並不是p一開始就指向了某個內容區域(前面說的常量區域)。根據這個現象可以推測,p就是放在棧中變數,而"hello world"是存在於乙個資料區域(堆區?可堆區是在執行時分配空間的?不大明白這些之間的概念)。

為了查詢真相,翻下對應的彙編**:

根據第一行彙編 , "hello world!"串應該存在0x0041573c處,從記憶體檢視器中檢視此處記憶體,確實存在這個串。這段彙編的作用就是通過幾組暫存器改變指向"hello world!"串不同的位置,將其搬運到 [ebp-18h]處的棧中(ebp[0x0012fe04]一般用於棧基位址)。

通過上面的分析可以知道,p是存在於棧區,指向的內容也在棧中,test函式返回的是test函式棧的乙個位址,而函式退出後,棧基址ebp發生變化,變為0x0012ff68(test中為 0x0012fe04),即為進入test前的棧基址,此時test函式棧的記憶體區域已不受保護,隨時可能被系統改寫內容,這就解釋了呼叫printf或者copystr時,str的內容發生了變化。

既然知道了原理,那就做些改進。乙個直接的想法就是將test函式中的p直接指向常量區域,將其改為static char p = "hello world!"即可,產生的彙編**就一句:mov         eax,offset p (417038h) 。

記一段刻骨民心的故事

清晨,攜著淡淡的秋風把孩子送進校園,一股股沁人心脾的桂花香迎面而來,我隨著誘人的桂花香,不經意又漫步在那些吹過花香和灑過秋雨的記憶裡 一年有四季,季季都會感觸,人的心為何永遠逃不掉那些風雨中的印記,想挪動腳,卻無法移步,總會在泥濘裡吶喊,在風雨裡痛苦,享受那些大自然帶來的折磨或快樂,明知是憂傷,卻喜...

一段簡單的ARM彙編分析

假設 段.text首位址為0x8054 錯誤的 示例 text code 32 global start start bl main 1.pc 0x8054,lr 0x0 b main push 2.pc 0x805c,lr 0x8058 bl func1 3.pc 0x8060,lr 0x8058...

一段真正令人感動的愛情故事

一段真正令人感動的愛情故事 希望大家能把這個的愛情故事看完,真的,真的很感動。在一次兩人共進晚餐的夜晚 女孩跟男孩提出分手的要求.男孩起先楞了一下 然後默默的接受了.女孩說我們還是好朋友 男孩說 恩 對呀 只要你有任何困難我一定會幫你的.然後像平時一樣傻笑.就這樣.平靜的吃完他們的最後一次晚餐 之後...