运行简单的字符串 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);
您可以使用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
【讨论】:
执行该操作的各种可能性很好理解。谢谢! “静态范围”? - 我认为您正在寻找的短语是“静态存储持续时间”。除此之外,一个很好的答案。【参考方案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
(来自 <stdlib.h>
比 0 更清晰)。
不带参数的函数应在 C 中声明为 void
。对于 main()
,空括号无效。
【讨论】:
我没有发现EXIT_SUCCESS
比零更清晰;这只是混乱。像FALSE
这样的宏也是如此。
感谢您的详细描述。我想我应该开始采用更正式的编程风格。但我无法理解 EXIT_SUCCESS 如何帮助更好地调试过程?以上是关于运行简单的字符串 C 程序时出现总线错误 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
每次在 vscode 中运行我的颤振应用程序时出现此错误 [重复]
使用 mysql 运行 JDBC 程序时出现此错误 [重复]
使用maven jetty插件在java 8上运行jetty 9时出现错误扫描文件[重复]