总线错误排查
我正在尝试反转字符串。
这是我尝试过的代码:
#include<stdio.h>
#include<string.h>
int main(){
char *c="I am a good boy";
printf("\n The input string is : %s\n",c);
printf("\n The length of the string is : %d\n",strlen(c));
int i,j;
char temp;
int len=strlen(c);
for(i=0,j=len-1;i<=j;i++,j--)
{
temp=c[i];
c[i]=c[j];
c[j]=temp;
//printf("%c\t%c\n",*(c+i),*(c+(len-i-1)));
}
printf("\n reversed string is : %s\n\n",c);
}
代码输出总线错误:10
。
但如果我重写相同的代码:
int main(void)
{
char *str;
str="I am a good boy";
int i,j;
char temp;
int len=strlen(str);
char *ptr=NULL;
ptr=malloc(sizeof(char)*(len));
ptr=strcpy(ptr,str);
for (i=0, j=len-1; i<=j; i++, j--)
{
temp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=temp;
}
printf("The reverse of the string is : %s\n",ptr);
}
它工作得很好。
为什么第一个代码会抛出总线错误或分段错误?
I am trying reverse a string.
This is the code I tried:
#include<stdio.h>
#include<string.h>
int main(){
char *c="I am a good boy";
printf("\n The input string is : %s\n",c);
printf("\n The length of the string is : %d\n",strlen(c));
int i,j;
char temp;
int len=strlen(c);
for(i=0,j=len-1;i<=j;i++,j--)
{
temp=c[i];
c[i]=c[j];
c[j]=temp;
//printf("%c\t%c\n",*(c+i),*(c+(len-i-1)));
}
printf("\n reversed string is : %s\n\n",c);
}
The code outputs a Bus error : 10
.
But if I rewrite the same code as:
int main(void)
{
char *str;
str="I am a good boy";
int i,j;
char temp;
int len=strlen(str);
char *ptr=NULL;
ptr=malloc(sizeof(char)*(len));
ptr=strcpy(ptr,str);
for (i=0, j=len-1; i<=j; i++, j--)
{
temp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=temp;
}
printf("The reverse of the string is : %s\n",ptr);
}
It works perfectly fine.
Why is the first code throwing bus error or segmentation fault?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
发生总线错误是因为在许多(如果不是大多数或所有现代)C 编译器中,字符串文字被分配在只读内存中。
您正在将字符串反转到位。在您的第一个代码片段中,您尝试写入字符串文字。这不是一个好主意。
在第二种情况下,您分配了一个字符串并将其放在堆上。现在可以安全地反转该字符串。
附录
对于询问段错误与总线错误的评论者来说,这是一个很好的问题。我都见过。这是 Mac 上的总线错误:
在其他操作系统/编译器上,您可能确实会遇到段错误。
The bus error occurs because in many (if not most or all modern) C compilers, string literals are allocated in read-only memory.
You are reversing the string in place. In your first code snippet you are trying to write into a string literal. Not a good idea.
In the second case, you malloc'd a string which put it on the heap. It is now safe to reverse that string in place.
ADDENDUM
To the commenter who asked about segfaults versus bus errors, that is a great question. I have seen both. Here is a bus error on a mac:
On other operating systems/compilers you may indeed get a segfault.
将其复制到堆是一种选择。但是,如果您只想分配一个本地(堆栈)数组,您可以这样做:
然后,常量字符串将被复制到堆栈中。
Copying it to the heap is one option. However, if you just want to allocate a local (stack) array, you can do:
Then, the constant string will be copied to the stack.
以
“我是个好孩子”
形式指定的字符数组通常是常量 - 您无法修改它们。这就是你的第一个变体崩溃的原因。第二个则不然,因为您复制了数据然后对其进行修改。Character arrays specified in form of
"I am a good boy"
are usually constant - you can't modify them. That's why your first variant crashes. The second doesn't, as you make a copy of data and then modify it.char *str = "我是个好孩子";视为文字并尝试修改它会导致总线错误。它相当于const char *str = "I am a good boy",即指向常量字符串的指针并试图修改常量字符串是不允许的。
编辑:当您 malloc() 和复制时,您正在使用原始字符串的副本,而 ptr 不是“const char *”类型,而是“char *ptr”类型,并且不会抱怨。
char *str = "I am a good boy"; Treated as literal and trying to modify it will result in bus error. It is equivalent to const char *str = "I am a good boy", i.e. pointer to a constant string and trying to modify a constant string is not allowed.
EDIT : The moment you malloc() and copy you are playing with a copy of the original string and ptr is not of 'const char *' type, instead it is 'char *ptr' and does not complain.
使用 c++ (g++) 编译显示不赞成将字符串文字分配给非常量 char*,这是为了防止出现此错误而设计的:
相关警告位于第 5 行。
将声明更改为 const char * 如所示,可防止分配到文字字符串。
这也是一个关于为什么不应忽略警告的教训。
Compiling with c++ (g++) shows the deprecation of assigning a string literal to a non-const char* which is designed to prevent this error:
The relevant warning is on line 5.
Changing the declaration to const char * as indicated prevents the assignments into the literal string.
This is also a lesson on why you should not ignore warnings.