为什么缓冲区溢出不会影响此代码?

我有以下代码:

int main(int argc, char *argv[]) { char ch[10]; printf("String 10 max. :: "); gets( ch ); printf("String: %s\n", ch); return 0; } 

当我使用"12345678"运行时,它运行良好。 奇怪的是当我用"123456789012345678901234567890"运行时! 第二个printf所有字符串(30个字符)打印到屏幕上。

为什么会这样? 为什么我的代码没有崩溃?

谢谢你的时间,
阿兹台克

您没有看到任何效果,因为您没有任何更多的局部变量,将代码更改为此,您将会

 int main(int argc, char *argv[]) { char ch[10]; int i=42; printf("String 10 max. :: "); gets( ch ); printf("String: %s\n", ch); printf("i: %d\n", i); return 0; } 

缓冲区溢出是未定义的行为。 它可能会崩溃,但没有人保证。 在大多数编译器中,堆栈会逐渐减少,因此您可能会覆盖main的返回地址,但是对printf的调用不会覆盖您的字符串。

如果您尝试从尚未映射的页面读取/写入,则缓冲区溢出仅导致“崩溃”(即,分段错误)。 在这种情况下,内存管理单元捕获错误。

如果你还没有到达页面末尾,就像在你的例子中那样,从操作系统/处理器的角度来看,那时的内存仍然有效 – 你只是覆盖了另一个变量可能使用的内存。

通过使用您不应该使用的内存,您将进入未定义行为的领域。 它今天不会在你的机器上崩溃。 但这种行为可能会在没有警告的情

对于它的价值,当我在我的cygwin shell上运行相同的代码时,我得到了

 Segmentation fault (core dumped) 

缓冲区溢出的影响完全取决于您覆盖的内容,覆盖它的内容以及随后使用的覆盖数据的方式。

缓冲区溢出利用的方法涉及使用溢出来修改函数的返回地址; 但是从main()返回到OS可能与从函数返回完全不同。