該內容源碼參考了 <深刻理解計算機系統>[3.10.3] 學習該章節以前,一直有個疑問,Segmentation fault 這樣的錯誤會具體引起的緣由是啥, 可不能夠從彙編代碼的層面進行一個學習和了解. 全部就有了這篇文章, 純屬我的學習研究. 完整的測試源碼 #include <stdio.h> #include <stdlib.h> #include <string.h> /* */ char* gets(char* s) { int c; char *dest = s; // read c char write to dest memory; while((c = getchar()) != '\n' && c != EOF) { *dest++= c; } if(c == EOF && dest == s) { return NULL; } *dest++ ='\0'; return s; } void echo(){ char buf[8]; gets(buf); puts(buf); } int main() { echo(); return 0; } 編譯過程, shell>gcc -g demo.c -o demo 程序編譯成功後,隨便輸入幾個字符, 能夠正常的回顯, 可是超過某個長度就會出現文章開始的問題, 那麼新的問題來了, 這個長度是否是就是代碼中定義的buf的長度呢, 會不會有其餘問題發生, 驗證思路: 1 經過彙編代碼, 查看寄存器地址中的內容, 直接明瞭的去觀察, 那麼就存在一個對比的過程, 第一遍的時候是正常的輸入, 不會發生錯誤, 第二遍會輸入較長的內容, 對比寄存器中的值. 正常輸入時, 在沒有輸入任何字符的時候, 相關的寄存器的值, 這個是在程序調用getchar() 函數前寄存器的值. (gdb) i r ebp ebp 0xbfffea68 0xbfffea68 (gdb) x/16cb 0xbfffea68 0xbfffea68: 120 'x' -22 '\352' -1 '\377' -65 '\277' 100 'd' -124 '\204' 4 '\004' 8 '\b' 0xbfffea70: 0 '\000' -106 '\226' 117 'u' 0 '\000' -112 '\220' -22 '\352' -1 '\377 ' -65 '\277' (gdb) i r esp esp 0xbfffea50 0xbfffea50 (gdb) x/16cb 0xbfffea50 0xbfffea50: -12 '\364' -1 '\377' -118 '\212' 0 '\000' 4 '\004' -30 '\342' -118 '\212' 0 '\000' 0xbfffea58: -120 '\210' -22 '\352' -1 '\377' -65 '\277' -87 '\251' -124 '\204' 4 '\004' 8 '\b' (gdb) i r eax eax 0xbfffea60 0xbfffea60 (gdb) x/16cb 0xbfffea60 0xbfffea60: 37 '%' -98 '\236' 121 'y' 0 '\000' 28 '\034' -21 '\353' -1 '\377' -65 '\277' 0xbfffea68: 120 'x' -22 '\352' -1 '\377' -65 '\277' 100 'd' -124 '\204' 4 '\004' 8 '\b' 開始調用getchar() 函數 此時有個隱藏的信息是, gets() 函數中, 參數s的地址是 0xbfffea60, 這個須要知道, 就是這個參數出現了問題, gdb> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 在輸入完成後, 再次查看寄存器的內容, (gdb) x/16cb 0xbfffea68 0xbfffea68: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 0xbfffea70: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' (gdb) x/32cb 0xbfffea50 0xbfffea50: 96 '`' -22 '\352' -1 '\377' -65 '\277' 4 '\004' -30 '\342' -118 '\2 12' 0 '\000' 0xbfffea58: -120 '\210' -22 '\352' -1 '\377' -65 '\277' -87 '\251' -124 '\204' 4 '\004' 8 '\b' 0xbfffea60: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 0xbfffea68: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' (gdb) x/16cb 0xbfffea60 0xbfffea60: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 0xbfffea68: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 對比發現 0xbfffea68 地址中的內容被改寫了, 這個地址是程序被調用時的入棧地址, 在gets()函數內部把值改寫了, 致使程序返回的時候,出現了問題, 若是用戶輸入了緩衝區大小內的內容後, 則器寄存器中的值爲 (gdb) x/16cb 0xbfffea60 0xbfffea60: 97 'a' 97 'a' 97 'a' 97 'a' 97 'a' 0 '\000' -1 '\377' -65 '\277' 0xbfffea68: 120 'x' -22 '\352' -1 '\377' -65 '\277' 100 'd' -124 '\204' 4 '\004' 8 '\b' 能夠發現 0xbfffea68地址中的值和原來的值是一致的, 此時程序退出則是正常的, 具體能夠使用的空間的大小的問題, 何時,會觸發返回地址被改寫.