本问题已经有最佳答案,请猛点这里访问。
我正在运行这个简单的程序,我得到的输出是"总线错误"。 使用一些调试语句,我发现它发生在strcat()调用处。
#include
#include
main()
{
char *s ="this is";
char *s1 ="me";
strcat(s,s1);
printf("%s",s);
return 0;
}
我在Mac 64位OS上使用gcc编译器运行它。 请让我知道是否需要提供更多规格。
谢谢!
"this is"和"me"是字符串文字,可以驻留在地址空间的只读部分中。您不应尝试修改它们。
char s[] ="this is";
char s1[] ="me";
这将确保将文字复制到堆栈中-这是可写的。然后,您后面的strcat将溢出堆栈缓冲区,这同样很糟糕。
以下内容将起作用-即使通常不使用strcat而不是strncat。
#include
#include
int main()
{
char s[100] ="this is";
char *s1 ="me";
strcat(s,s1);
printf("%s",s);
return 0;
}
对于不知道如何正确使用它的人来说,strcat只是不好的做法。这些人应该坚持使用BASIC :-)但是+1,因为您已将其钉牢。
@paxdiablo:是的,因此"一般";)
哇,让我记得很久以前发生在我身上的一个讨厌的错误。我遇到了段错误,然后才意识到这很困难。
当程序变得复杂时,要跟踪字符串的大小确实非常困难。感谢您指出警告。.请注意!
一点背景:
表达式"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不同):
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
执行该操作的各种可能性值得关注。谢谢!
"静态程度"? -我认为您要查找的短语是"静态存储期限"。除此之外,一个很好的答案。
您需要阅读更多有关字符串如何在C中工作以及字符数组和字符串文字之间的区别的更多信息。
为此,请按如下所示对其进行重写:
#include
#include
#include
int main(void)
{
char s[100] ="this is";
char *s1 ="me";
strcat(s, s1);
printf("%s", s);
return EXIT_SUCCESS;
}
还有几点:
main()返回int。
符号EXIT_SUCCESS(来自的符号清零)。
在C中,不带参数的函数应声明为void。对于main(),空括号无效。
我发现EXIT_SUCCESS不会比零更清晰;它只是混乱。像FALSE这样的宏也是如此。
感谢您的详细说明。我想我应该开始采用一种更正式的编程风格。但是我无法理解EXIT_SUCCESS如何为更好的调试过程提供帮助?