【问题标题】:Printing char array in C causes segmentation fault在 C 中打印 char 数组会导致分段错误
【发布时间】:2014-10-23 00:44:11
【问题描述】:

我为此做了很多搜索,找不到任何具有相同问题的问题。

这是我的代码:

void fun(char* name){
    printf("%s",name);
}

char name[6];
sscanf(input,"RECTANGLE_SEARCH(%6[A-Za-z0-9])",name)
printf("%s",name);
fun(name);

该名称是从scanf 中获取的,一开始打印得很好。然后在调用fun 时,在尝试打印名称时出现分段错误。这是为什么呢?

【问题讨论】:

  • 您应该在问题中包含scanf 行。
  • 名称的大小(即6)似乎很小。如果将其增加到 100 会怎样。
  • 我包含了 scanf 行。 6 是我正在使用的最大字符长度
  • 什么是searchName?不应该是name吗?
  • 对不起,我把代码改了一些,忘记了^

标签: c string segmentation-fault


【解决方案1】:

查看我的占卜镜后,我找到了:

您的scanf 确实溢出了缓冲区(超过 6 个字节,包括终止符读取),由于环境原因,影响略有延迟:

没有其他人依赖或重新使用最初损坏的内存,因此第一个 printf 似乎可以工作。

在第一次调用 printf 之后和第二次调用之前的某个地方,您覆盖的空间被重新使用,因此您读取的字符串在遇到未分配的页面之前不再终止。
因此,最后出现了分段错误。

当然,您的程序在溢出缓冲区的那一刻就被烤了,而不是在它最终崩溃的时候。
士气:永远不要写你没有为此付出的记忆。

查看您的编辑,%6[A-Za-z0-9] 格式尝试读取最多 6 个字符,不包括终止符,不包括在内!

【讨论】:

  • 我在函数调用之前尝试调用 printf 两次,它成功打印了两次名称然后 segfault
  • 谢谢!我把 6 换成了 5 和中提琴!
  • 很高兴为您提供帮助。请记住,如果您违反合同(调用 UB,例如通过溢出缓冲区),则无法保证您何时、是否或如何被抓住,也不保证会发生什么。 UB 可以是微妙的或严厉的,明显的或没有效果的。
  • @GregBrinker 看起来name 是在堆栈上分配的,这意味着写入第 7 个和以后的字节会破坏现有堆栈,一旦您尝试调用另一个字节就会导致讨厌的事情发生函数 (fun),或者如果您的编译器以其他方式工作,通过调用 fun 分配和使用新的堆栈帧将覆盖悬空的第 7 个以上字节。
  • 移除弦乐器可能是未定义行为的影响
【解决方案2】:

由于您正在阅读 6 个字符,因此您必须将 name 声明为 7 个字符,因此终止空字符有空间:

char name[7];

否则,你会得到一个缓冲区溢出,后果是不确定的。一旦你有未定义的后果,任何事情都可能发生,包括 2 次成功调用 printf(),然后在调用另一个函数时出现段错误。

【讨论】:

    【解决方案3】:

    您可能正在使用您的 printf 语句离开数组的末尾。 Printf 使用终止空字符 '\0' 来知道字符串的结尾在哪里。尝试像这样分配您的数组:

    char name[6] = {'\0'};
    

    这将为您的数组分配初始设置为“\0”字符的每个元素,这意味着只要您不使用 scanf 覆盖整个数组,printf 将在结束之前终止。

    【讨论】:

    • scanf 将始终以 0 终止读取的字符串。除非格式说明符是%c 用于任何字符
    【解决方案4】:

    您确定name 是零字节终止的吗? scanf 可能会根据您的调用方式溢出缓冲区。

    如果发生这种情况,那么 printf 将读取超出数组末尾的内容,从而导致未定义的行为并可能出现分段错误。

    【讨论】:

    • 这并没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
    • 当时这是在没有scanf 的细节的情况下可以给出的最佳答案。
    猜你喜欢
    • 2021-01-29
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多