数组不';t溢出(C语言)

数组不';t溢出(C语言),c,arrays,overflow,scanf,C,Arrays,Overflow,Scanf,如果我尝试运行此代码,并将例如“Hello”(超过3个字符)作为scanf的输入,则数组str不会溢出。这听起来有点奇怪,但我当然错过了一些东西。有人知道这里有什么问题吗?非常感谢 char str[3]; scanf("%s", str); printf("%s\n", str); 我试着运行你的代码,但它没有: ./main ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue ofejnhofewnho

如果我尝试运行此代码,并将例如“Hello”(超过3个字符)作为
scanf
的输入,则数组
str
不会溢出。这听起来有点奇怪,但我当然错过了一些东西。有人知道这里有什么问题吗?非常感谢

char str[3];
scanf("%s", str);
printf("%s\n", str);

我试着运行你的代码,但它没有:

./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
0x000000000040057d:推送%rbp
0x000000000040057e:mov%rsp,%rbp
0x0000000000400581:子$0x20,%rsp
sub 0x20
是32个字节,显然超过了3个字节

不要期望一个严格的“伪”C到汇编指令,现在编译器执行的优化和决策比您可能知道的要多


试图找到缓冲区和EIP之间的确切字节范围通常需要执行蛮力,但聪明的黑客可能会找到更有趣的方法…;-)

我试图运行您的代码,但它没有:

./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
0x000000000040057d:推送%rbp
0x000000000040057e:mov%rsp,%rbp
0x0000000000400581:子$0x20,%rsp
sub 0x20
是32个字节,显然超过了3个字节

不要期望一个严格的“伪”C到汇编指令,现在编译器执行的优化和决策比您可能知道的要多


试图找到缓冲区和EIP之间的确切字节范围通常需要执行蛮力,但聪明的黑客可能会找到更有趣的方法…;-)

C运行时不会发出错误/警告消息,但会产生不正确的结果。
检查溢流/下溢是您的责任

C运行时不会发出错误/警告消息,但会产生不正确的结果。 检查溢流/下溢是您的责任

你说,“数组
str
没有溢出”,但你怎么知道?您认为溢出是如何表现出来的

事实上,数组确实溢出了。你只是得到了“幸运”,没有(可见的)反响

关于计算机编程,需要理解的一件棘手的事情是规则的执行可能非常不一致。(在这方面,计算机编程与生活没有什么不同。)如果十字路口的信号灯上写着“不要走”,但没有车来,所以你无论如何都要过马路,如果没有警察立即出现并为你开出乱穿马路的罚单,你会有多惊讶?这就是这里发生的基本情况。

你说过,“数组
str
不会溢出”,但你怎么知道?您认为溢出是如何表现出来的

事实上,数组确实溢出了。你只是得到了“幸运”,没有(可见的)反响


关于计算机编程,需要理解的一件棘手的事情是规则的执行可能非常不一致。(在这方面,计算机编程与生活没有什么不同。)如果十字路口的信号灯上写着“不要走”,但没有车来,所以你无论如何都要过马路,如果没有警察立即出现并为你开出乱穿马路的罚单,你会有多惊讶?这基本上就是这里发生的事情。

覆盖数组的边界是错误的。如果你说的“不溢出”是指“打印时没有分段故障”,那么这次你就幸运了。“Hello”不能放入
str
,因此您的代码溢出了。或者真的很不走运,因为你会认为一切都很好,然后你的程序会在你最不希望的时候崩溃。这并不是真的相关,只是要注意输入2个以上的字符会调用ub。您可以使用一些运行时工具来捕获此类错误,警告标志不会捕获此类错误,但对于捕获其他ub调用代码(例如尝试读取未初始化的变量)仍然很有用。请使用“char str[4096];”和"sscanf"("4096s,str);。这应该足够大了?@MartinJames——应该是
scanf(“%4095s”,str)
为空终止符留出空间。要使用
sscanf()
您需要为输入字符串添加另一个参数。覆盖数组边界的可能重复项为。如果你说的“不溢出”是指“打印时没有分段故障”,那么这次你就幸运了。“Hello”不能放入
str
,因此您的代码溢出了。或者真的很不走运,因为你会认为一切都很好,然后你的程序会在你最不希望的时候崩溃。这并不是真的相关,只是要注意输入2个以上的字符会调用ub。您可以使用一些运行时工具来捕获此类错误,警告标志不会捕获此类错误,但对于捕获其他ub调用代码(例如尝试读取未初始化的变量)仍然很有用。请使用“char str[4096];”和"sscanf"("4096s,str);。这应该足够大了?@MartinJames——应该是
scanf(“%4095s”,str)
为空终止符留出空间。要使用
sscanf()
,您需要为输入字符串添加另一个参数。可能与它重复。谢谢:)明白了。谢谢:)