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

Mav*_*ugu 4 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;
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Eri*_*rik 8

"this is "并且"me"是字符串文字,可以驻留在地址空间的只读部分.您不应该尝试修改这些.

char s[] = "this is ";
char s1[] = "me";  
Run Code Online (Sandbox Code Playgroud)

这将确保将文字复制到堆栈 - 这是可写的.然后你的下面的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;
}
Run Code Online (Sandbox Code Playgroud)

  • `strcat`对于那些不知道如何正确使用它的人来说只是不好的做法.这些人应该坚持使用BASIC :-)但是+1你自己钉了它. (3认同)

Joh*_*ode 8

一点背景:

表达"this is ""me"字符串常量 ; 它们分别是char (const charC++中)的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);
    
    Run Code Online (Sandbox Code Playgroud)

  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);
    
    Run Code Online (Sandbox Code Playgroud)

  3. 您可以使用malloc或动态分配目标缓冲区calloc(这实际上是首选方法,因为缓冲区可以根据需要调整大小,与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
    
    Run Code Online (Sandbox Code Playgroud)