运行简单的字符串 C 程序时出现总线错误 [重复]

Posted

技术标签:

【中文标题】运行简单的字符串 C 程序时出现总线错误 [重复]【英文标题】:Bus error while running a simple string C program [duplicate] 【发布时间】:2011-08-08 16:46:45 【问题描述】:

我正在运行这个简单的程序,我得到的输出是“总线错误”。使用一些调试语句,我发现它发生在 strcat() 调用中。

#include<stdio.h>
#include<string.h>
main()

char *s = "this is ";
char *s1 = "me";  
strcat(s,s1); 
printf("%s",s);
return 0;

我在 MAC、64 位操作系统上使用 gcc 编译器运行它。如果我需要提供更多规格,请告诉我。

谢谢!

【问题讨论】:

【参考方案1】:

一点背景:

表达式"this is ""me"字符串字面量;它们分别是具有静态范围的char(C++ 中的const char)的 9 元素和 3 元素数组(意味着它们的内存在程序启动时分配并保持到程序退出)。该内存可能是可写的,也可能不是可写的,这取决于平台,因此尝试修改字符串文字会导致未定义的行为(这意味着编译器实际上可以做任何它想做的事情)。简而言之,您不能写入字符串文字。

当你写strcat(s, s1); 时,你会遇到两个问题:首先,目标数组是一个字符串字面量,正如我上面提到的,它是不可写的。其次,它不够大,无法容纳额外的字符;它的大小可容纳 9 个字符(包括 0 终止符),但您正尝试向其存储 11 个字符。这是一个缓冲区溢出,如果你破坏了一些重要的东西,可能会导致坏事。

您必须分配一个可写的目标缓冲区。您有多种选择:

    您可以声明一个大到足以容纳结果字符串的数组,尽管一般在编译时您不会知道“足够大”有多大:

    
    char *s = "this is ";
    char *s1 = "me";
    char target[11];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

    在 C99 中,您可以声明一个可变长度数组 (VLA),其大小直到运行时才知道:

    
    char *s = "this is ";
    char *s1 = "me";
    char target[strlen(s) + strlen(s1) + 1];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

    您可以使用malloccalloc 动态分配目标缓冲区(这实际上是首选方法,因为可以根据需要调整缓冲区的大小,这与VLA 不同):

    
    char *s = "this is ";
    char *s1 = "me";
    char *target = malloc(strlen(s) + strlen(s1) + 1);
    strcpy(target, s);
    strcat(target, s1); 
    // or sprintf(target, "%s%s", s, s1);
    ...
    free(target); // when you're finished with the buffer
    

【讨论】:

执行该操作的各种可能性很好理解。谢谢! “静态范围”? - 我认为您正在寻找的短语是“静态存储持续时间”。除此之外,一个很好的答案。【参考方案2】:

"this is ""me" 是字符串文字,它们可能驻留在地址空间的只读部分中。您不应该尝试修改这些。

char s[] = "this is ";
char s1[] = "me";  

这将确保文字被复制到堆栈 - 这是可写的。然后你下面的 strcat 将溢出堆栈缓冲区,这同样糟糕。

以下内容将起作用 - 即使使用 strcat 而不是 strncat 通常是不好的做法。

#include <stdio.h>
#include <string.h>
int main()

  char s[100] = "this is ";
  char *s1 = "me";  
  strcat(s,s1); 
  printf("%s",s);
  return 0;

【讨论】:

strcat 对于那些不知道如何正确使用它的人来说只是不好的做法。这些人应该坚持使用 BASIC :-) 但是 +1,因为你已经搞定了。 @paxdiablo:是的,因此“一般”;) 哇,让我想起了很久以前发生在我身上的一个讨厌的错误。我遇到了段错误,然后很难意识到这一点。 当程序变得复杂时,很难跟踪字符串的大小。感谢您指出警告.. 会注意的!【参考方案3】:

您需要详细了解字符串在 C 中的工作原理,以及字符数组和字符串字面量之间的区别。

为了使这个工作,例如重写它如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)

  char s[100] = "this is ";
  char *s1 = "me";  

  strcat(s, s1); 

  printf("%s", s);

  return EXIT_SUCCESS;

还有几点:

    main() 返回int。 符号 EXIT_SUCCESS(来自 &lt;stdlib.h&gt; 比 0 更清晰)。 不带参数的函数应在 C 中声明为 void。对于 main(),空括号无效。

【讨论】:

我没有发现EXIT_SUCCESS 比零更清晰;这只是混乱。像FALSE 这样的宏也是如此。 感谢您的详细描述。我想我应该开始采用更正式的编程风格。但我无法理解 EXIT_SUCCESS 如何帮助更好地调试过程?

以上是关于运行简单的字符串 C 程序时出现总线错误 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

每次在 vscode 中运行我的颤振应用程序时出现此错误 [重复]

使用 mysql 运行 JDBC 程序时出现此错误 [重复]

使用maven jetty插件在java 8上运行jetty 9时出现错误扫描文件[重复]

将字符串转换为 int 时出现语法错误 [重复]

使用getSupportActionBar时出现NullPointerException [重复]

当我尝试在 sequel pro 中运行此查询时出现错误 [重复]