该内容源码参考了 <深刻理解计算机系统>[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地址中的值和原来的值是一致的, 此时程序退出则是正常的, 具体能够使用的空间的大小的问题, 何时,会触发返回地址被改写.