C 返回后的分段错误?

C 返回后的分段错误?,c,C,执行return后,我得到分段错误。为什么它是回来后,而不是在strcpy int main() { char a[2]; strcpy(a,"0123456789101112131415161718192021222324252627282930"); printf("%s\n",a); return 0; } 您试图将一个包含多于2个字符的字符串加载到一个仅包含2个字符的字符数组中。这将导致分段错误,因为您正在覆盖为字符数组分配的内存,这也可

执行return后,我得到
分段错误
。为什么它是回来后,而不是在strcpy

int main()
{

     char a[2];

     strcpy(a,"0123456789101112131415161718192021222324252627282930");
     printf("%s\n",a);

     return 0;

}

您试图将一个包含多于2个字符的字符串加载到一个仅包含2个字符的字符数组中。这将导致分段错误,因为您正在覆盖为字符数组分配的内存,这也可能导致未定义的行为。

您的程序重写了缓冲区,这将导致未定义的行为,这意味着任何事情都可能发生

为什么它是回来后,而不是在strcpy

int main()
{

     char a[2];

     strcpy(a,"0123456789101112131415161718192021222324252627282930");
     printf("%s\n",a);

     return 0;

}
main
返回时,由于覆盖了
main
函数堆栈帧中的关键数据(保存的帧指针和返回地址),而不是
strcpy
函数堆栈帧中的关键数据,因此会出现分段错误

正如其他人已经说过的,你调用未定义的行为,任何事情都可能发生:从无到有到核战争

在return执行后,我遇到了分段错误。为什么它是回来后,而不是在strcpy

int main()
{

     char a[2];

     strcpy(a,"0123456789101112131415161718192021222324252627282930");
     printf("%s\n",a);

     return 0;

}
你犯了一个常见的错误,叫做。这会导致未定义的行为,这是一个标准答案。然而,如果您了解一台典型的机器是如何使用的,那么您就可以理解它在返回时崩溃的原因。大多数CPU使用向下增长的堆栈。因此,在调用strcpy之前,堆栈如下所示:

sp + 0 : a[0]
sp + 1 : a[1]
sp + 2 : padding
sp + 3 : padding
sp + 4: return address (four bytes)
每次您在“C”中使用函数时,编译器机制都会创建一个。返回地址作为堆栈的一部分存在,编译器在堆栈中为[]数组分配空间。由于字符串副本的大小不足,因此您会过度写入返回地址。在返回之前不会使用此值。返回地址将被类似值
0x34353637
的内容覆盖,该值是ASCII文本“4567”的二进制指针

建议使用或。比如说,

strncpy(a,"012345678...", sizeof(a));
a[sizeof(a)-1] = 0;   /* ensure the string is terminated. */

显然,如果希望打印完整字符串,则需要增加“a”数组的大小

这是未定义的行为。分段错误是一个合理的结果:)您试图将一个长字符串复制到一个2个字符的数组中……strcpy将数据写入堆栈,这肯定会成功。但是它很可能会破坏存储在堆栈上的返回地址,因此返回跳到无效位置。分段错误是未定义行为的(幸运的)表现。OP的问题不是它为什么会导致segfault,而是它为什么会在返回时发生,而不是在
strcpy
。正如我在回答中所述,发生这种情况是因为您正在覆盖为该字符数组分配的内存位置。未定义的行为意味着任何事情都可能发生;有可能覆盖程序的指令代码,也有可能覆盖内存中其他地方的另一个变量,等等。要准确地知道发生了什么,确实没有简单的方法。可能是指令代码被覆盖,导致执行跳转到内存中的其他位置,导致SEGFULT…我相当确定,当我的代码中遇到未定义的行为时,我的工具链中的任何东西都不可能导致核战争。(如果我在NORAD工作,我可能就不那么确定了。)