问题
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?
回答1:
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:
$ cat bus.c
char* s = "abc"; int main() {s[0]='d'; return 0;}
$ gcc --version bus.c && ./a.out
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Bus error
On other operating systems/compilers you may indeed get a segfault.
回答2:
Copying it to the heap is one option. However, if you just want to allocate a local (stack) array, you can do:
char str[] = "I am a good boy";
Then, the constant string will be copied to the stack.
回答3:
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.
回答4:
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.
回答5:
Compiling with c++ (g++) shows the deprecation of assigning a string literal to a non-const char* which is designed to prevent this error:
ed@bad-horse:~/udlit_debug$ g++ ../buserr.cpp
../buserr.cpp: In function ‘int main()’:
../buserr.cpp:5:13: warning: deprecated conversion from string constant to ‘char*’
../buserr.cpp:7:61: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’
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.
来源:https://stackoverflow.com/questions/7458854/bus-error-troubleshooting