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

时间:2011-04-19 13:32:42

标签: c string strlen bus-error

我正在运行这个简单的程序,我得到的输出是“总线错误”。使用一些调试语句,我发现它发生的点是在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编译器运行它。如果我需要提供更多规格,请告诉我。

谢谢!

3 个答案:

答案 0 :(得分:8)

"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;
}

答案 1 :(得分:7)

一点背景:

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

当您编写strcat(s, s1);时,您遇到两个问题:首先,目标数组是字符串文字,如上所述,它是不可写的。其次,它不足以容纳额外的角色;它的大小可以容纳9个字符(包括0个终结符),但是你试图存储11个字符。这是一个缓冲区溢出,如果你破坏了一些重要的东西,可能会导致糟糕的事情。

您必须分配可写的目标缓冲区。你有几个选择:

  1. 你可以声明一个足够大的数组来保存结果字符串,虽然一般你不会知道在编译时有多大“足够大”:

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

  2. 在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);
    

  3. 您可以使用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 :(得分:2)

您需要详细了解字符串在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;
}

还有几点:

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