Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
运行简单字符串C程序时发生总线错误_C_String_Strlen_Bus Error - Fatal编程技术网

运行简单字符串C程序时发生总线错误

运行简单字符串C程序时发生总线错误,c,string,strlen,bus-error,C,String,Strlen,Bus Error,我运行这个简单的程序,得到的输出是“总线错误”。使用一些调试语句,我发现它发生在strcat()调用处 #包括 #包括 main() { char*s=“这是”; char*s1=“我”; strcat(s,s1); printf(“%s”,s); 返回0; } 我在MAC 64位操作系统上使用gcc编译器运行它。请让我知道,如果我需要提供任何更多的规格 谢谢 “这是”和“我”是字符串文字,可能位于地址空间的只读部分。您不应该试图修改这些 char s[] = "this is "; char

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

#包括
#包括
main()
{
char*s=“这是”;
char*s1=“我”;
strcat(s,s1);
printf(“%s”,s);
返回0;
}
我在MAC 64位操作系统上使用gcc编译器运行它。请让我知道,如果我需要提供任何更多的规格

谢谢

“这是”
“我”
是字符串文字,可能位于地址空间的只读部分。您不应该试图修改这些

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;
}
#包括
#包括
int main()
{
char s[100]=“这是”;
char*s1=“我”;
strcat(s,s1);
printf(“%s”,s);
返回0;
}

您需要进一步了解字符串在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;
}
#包括
#包括
#包括
内部主(空)
{
char s[100]=“这是”;
char*s1=“我”;
strcat(s,s1);
printf(“%s”,s);
返回退出成功;
}
还有几点:

  • main()
    返回
    int
  • 符号
    退出\u SUCCESS
    (from
    比0清晰)
  • 在C中,不带参数的函数应声明为
    void
    。对于
    main()
    ,空括号无效
  • 一点背景:

    表达式
    “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);
    
  • 您可以使用
    malloc
    calloc
    动态分配目标缓冲区(这实际上是首选方法,因为与VLA不同,缓冲区可以根据需要调整大小):


  • strcat
    对于那些不知道如何正确使用它的人来说只是一种不好的做法。这些人应该坚持使用BASIC:-)但是+1,因为你已经搞定了它。@paxdiablo:是的,所以“一般”是这样的哇,让我想起了很久以前发生在我身上的一个讨厌的虫子。当程序变得复杂的时候,跟踪字符串的大小肯定很困难。谢谢你指出这个警告。。你会知道的!我没有发现
    EXIT\u SUCCESS
    比零更清晰;只是乱七八糟。类似于
    FALSE
    的宏也是如此。感谢您的详细描述。我想我应该开始采用一种更正式的编程风格。但我无法理解EXIT_成功如何有助于更好的调试过程?执行该操作的各种可能性很好遵循。谢谢“静态范围”?-我认为您要寻找的短语是“静态存储持续时间”。除此之外,这是一个很好的回答。
    
    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);
    
    
    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