如果我尝试运行此代码并提供例如“Hello”(超过3个字符)作为scanf
的输入,则数组str
不会溢出。这对我来说听起来有点奇怪,但当然我错过了一些东西。有谁知道这里的问题是什么?非常感谢!
char str[3];
scanf("%s", str);
printf("%s\n", str);
答案 0 :(得分:2)
你说,"阵列str
并没有溢出"但你怎么知道?您是如何期望溢出显现的?
实际上,数组已经溢出。你刚刚得到了#34;幸运"并且没有(可见的)反响。
理解计算机编程的一个棘手问题是规则的执行可能非常不一致。 (计算机编程与生活在这方面并没有什么不同。)如果交叉路口的信号表示“不要走路”,但是没有车来,所以你无论如何都要过马路,你有多惊讶没有警察立即出现,并写了一张jaywalking票?这基本上就是这里发生的事情。
答案 1 :(得分:1)
我试图运行你的代码,它确实是段错误的:
./main
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue
Segmentation fault (core dumped)
我不知道你试图传递多少个字符scanf()
但是你必须知道有时编译器会在保存的ESP / EIP和初始变量之间执行填充。
特别是,在这里,您要在堆栈上创建一个3字节的内存区域,编译器首先将其四舍五入为4(或者在x64上为8?)。但即便如此,它可能会增加更多空间。
在gdb
中,disass main
给了我:
0x000000000040057d <+0>: push %rbp
0x000000000040057e <+1>: mov %rsp,%rbp
0x0000000000400581 <+4>: sub $0x20,%rsp
sub 0x20
是32个字节,显然超过3个字节。
不要指望严格的“虚拟”C到汇编程序指令,现在编译器执行了许多优化和决策,而不是你可能知道的。
试图找到缓冲区和EIP之间的确切字节范围通常需要执行蛮力,但聪明的黑客可能会找到更有趣的方法......; - )
答案 2 :(得分:1)
C运行时不会发出错误/警告消息,但会产生错误的结果。 要检查溢出/下溢是您的责任。