Устранение ошибок шины - PullRequest
       8

Устранение ошибок шины

8 голосов
/ 18 сентября 2011

Я пытаюсь перевернуть строку.

Это код, который я пробовал:

#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);
}

Код выводит Bus error : 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);
}

Работает отлично.

Почему возникает первая ошибка шины выброса кода или ошибка сегментации?

Ответы [ 5 ]

16 голосов
/ 18 сентября 2011

Ошибка шины возникает из-за того, что во многих (если не в большинстве или во всех современных) компиляторах C строковые литералы размещаются в постоянной памяти.

Вы переворачиваете строку на месте. В своем первом фрагменте кода вы пытаетесь записать строковый литерал. Не очень хорошая идея.

Во втором случае вы malloc'd строку, которая помещает его в кучу. Теперь безопасно перевернуть эту строку на месте.

ДОПОЛНЕНИЕ

Для комментатора, который задал вопрос о segfaults и автобусных ошибках, это отличный вопрос. Я видел оба. Вот ошибка шины на 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

В других операционных системах / компиляторах вы действительно можете получить ошибку.

6 голосов
/ 18 сентября 2011

Копирование в кучу - один из вариантов. Однако, если вы просто хотите выделить локальный (стек) массив, вы можете сделать:

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

Затем константная строка будет скопирована в стек.

1 голос
/ 18 сентября 2011

Символьные массивы, указанные в форме "I am a good boy", обычно являются постоянными - их нельзя изменить. Вот почему ваш первый вариант вылетает. Второе - нет, поскольку вы делаете копию данных, а затем изменяете ее.

0 голосов
/ 24 сентября 2011

Компиляция с помощью c ++ (g ++) показывает, что устаревшее назначение строкового литерала неконстантному символу * запрещено, что предназначено для предотвращения этой ошибки:

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 *, как указано, предотвращает присваивания в буквенную строку.

Это также урок о том, почему вы не должны игнорировать предупреждения.

0 голосов
/ 18 сентября 2011

char * str = "Я хороший мальчик"; Рассматривается как литерал, и попытка изменить его приведет к ошибке шины. Это эквивалентно const char * str = "Я хороший мальчик", то есть указатель на постоянную строку и попытка изменить постоянную строку недопустимы.

РЕДАКТИРОВАТЬ: В тот момент, когда вы выполняете malloc () и копируете, вы играете с копией оригинальной строки, и ptr не имеет типа «const char *», вместо этого это «char * ptr» и не жалуется.

...