有人可以澄清一下吗?
char str[1];
strcpy(str, "HHHHHHHHHHHH");
在这里,我声明了一个大小为 1 的 char 数组,但程序不会崩溃,直到我输入超过 12 个字符并且我只有一个大小为 1 的数组。为什么?
此代码具有未定义的行为,因为它写入了多个元素str
。它可以做任何事情。您有责任确保只写入您拥有的内存。
这是未定义的行为。在实践中,您会覆盖某些内容的内存内容。在这种情况下,如果该数组是局部变量,则该数组将进入堆栈。很可能您的 CPU 架构中堆栈会向下增长,因此您开始覆盖其他局部变量、保存的寄存器值和函数调用的返回地址等内容。
您可能首先覆盖了没有立即影响的内容,或者您没有注意到效果。这可能是一个尚未初始化的局部变量,或者是一个局部变量或保存的寄存器值,在您覆盖它之后实际上并没有使用它。
然后当你增加溢出长度时,你可能损坏了函数返回地址,然后当你从函数返回时实际上发生了崩溃。如果您有任何其他内存地址,即指针,崩溃也可能是因为您试图访问损坏的指针指向的值。
最后,如果您将溢出大小增加到足够大,字符串复制最终将直接写入允许区域之外并导致立即崩溃(假设 CPU 和 OS 具有此类内存保护,而不是某些古老或嵌入式系统)。但这可能不是这里的原因,因为您在崩溃前只写了 14 个字节。
但是请注意,从 C 语言的角度来看,上述内容有点毫无意义,未定义的行为,如果您更改程序中的任何内容、编译器选项或输入数据,它通常会发生变化。这可能会使内存损坏错误难以找到,因为添加调试内容通常会使问题“消失”(更改或隐藏症状)。