C语言中的字符串内存分配

C语言中的字符串内存分配,c,arrays,memory,char,C,Arrays,Memory,Char,有人能澄清一下吗 char str[1]; strcpy(str, "HHHHHHHHHHHH"); 在这里,我声明了一个大小为1的字符数组,但是直到我输入超过12个字符并且只有一个大小为1的数组,程序才会崩溃。为什么?此代码具有未定义的行为,因为它将多个元素写入str。它可以做任何事。您有责任确保只将自己拥有的内容写入内存。这是未定义的行为。实际上,您覆盖了某些内容的内存内容。在本例中,如果该数组是局部变量,则该数组将进入堆栈。很可能您有一个CPU架构,其中堆栈会减少,因此您开始覆盖其他局部

有人能澄清一下吗

char str[1];
strcpy(str, "HHHHHHHHHHHH");

在这里,我声明了一个大小为1的字符数组,但是直到我输入超过12个字符并且只有一个大小为1的数组,程序才会崩溃。为什么?

此代码具有未定义的行为,因为它将多个元素写入
str
。它可以做任何事。您有责任确保只将自己拥有的内容写入内存。

这是未定义的行为。实际上,您覆盖了某些内容的内存内容。在本例中,如果该数组是局部变量,则该数组将进入堆栈。很可能您有一个CPU架构,其中堆栈会减少,因此您开始覆盖其他局部变量、保存的寄存器值和函数调用的返回地址等内容

您可能首先过度编写了一些没有立即效果的内容,或者您没有注意到效果。这可能是一个尚未初始化的局部变量,也可能是一个在重写后未实际使用的局部变量或保存的寄存器值

然后,当您增加溢出长度时,可能会损坏函数返回地址,然后在您从函数返回时实际发生崩溃。如果您有任何其他内存地址,即指针,崩溃也可能是因为您试图访问损坏指针所指向的值

最后,如果您将溢出大小增加到足够大,字符串复制最终将直接写入允许的区域之外,并导致立即崩溃(假设CPU和操作系统具有这样的内存保护,而不是一些古老的或嵌入式系统)。但这可能不是原因,因为您在崩溃之前只写了14个字节


但请注意,从C语言的角度来看,上述行为是毫无意义的,未定义的行为,如果您更改程序、编译器选项或输入数据中的任何内容,这些行为通常会发生变化。这会使内存损坏bug难以发现,因为添加调试内容通常会使问题“消失”(更改或隐藏症状)。

恭喜您找到了一个UB!这是一个例子。不完全相同的情况,但对发生的事情有相同的解释。@POW,使用这个缩写是为了让人们问“UB的定义是什么?”?那太卑鄙了。我喜欢这本书。我想我们几乎每天都有这类问题。请在询问之前搜索该网站。可能是我的复制品只是好奇谢谢@这可能有用。