总线错误排查

发布于 2024-12-04 21:25:40 字数 1029 浏览 0 评论 0原文

我正在尝试反转字符串。

这是我尝试过的代码:

#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

空宴 2024-12-11 21:25:40

发生总线错误是因为在许多(如果不是大多数或所有现代)C 编译器中,字符串文字被分配在只读内存中。

您正在将字符串反转到位。在您的第一个代码片段中,您尝试写入字符串文字。这不是一个好主意。

在第二种情况下,您分配了一个字符串并将其放在堆上。现在可以安全地反转该字符串。

附录

对于询问段错误与总线错误的评论者来说,这是一个很好的问题。我都见过。这是 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

在其他操作系统/编译器上,您可能确实会遇到段错误。

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.

逆流 2024-12-11 21:25:40

将其复制到堆是一种选择。但是,如果您只想分配一个本地(堆栈)数组,您可以这样做:

char str[] = "I am a good boy";

然后,常量字符串将被复制到堆栈中。

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.

梦过后 2024-12-11 21:25:40

“我是个好孩子” 形式指定的字符数组通常是常量 - 您无法修改它们。这就是你的第一个变体崩溃的原因。第二个则不然,因为您复制了数据然后对其进行修改。

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.

注定孤独终老 2024-12-11 21:25:40

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.

前事休说 2024-12-11 21:25:40

使用 c++ (g++) 编译显示不赞成将字符串文字分配给非常量 char*,这是为了防止出现此错误而设计的:

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’

相关警告位于第 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:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文