2011-09-18 7 views
8

Estoy intentando invertir una cadena.Solución de problemas de error de bus

Este es el código Traté:

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

El código da salida a una Bus error : 10.

Pero si vuelvo a escribir el mismo código que:

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

Funciona perfectamente bien.

¿Por qué es el primer código que lanza un error de bus o una falla de segmentación?

+1

por favor reformatee su código. –

+0

Traté de formatear tanto como sea posible, pero realmente no sé cómo alinearlos. – sethu

+1

Formatee su código sangrándolo todo con cuatro espacios. – SLaks

Respuesta

16

El error de bus ocurre porque en muchos compiladores de C (si no todos o todos), los literales de cadena se asignan en la memoria de solo lectura.

Está invirtiendo la cadena en su lugar. En el primer fragmento de código, intenta escribir en un literal de cadena. No es Buena idea.

En el segundo caso, malloc'd una cadena que lo puso en el montón. Ahora es seguro invertir esa cadena en su lugar.

ADENDA

Para el autor del comentario que le preguntó acerca segfaults frente a los errores del bus, que es una gran pregunta. He visto ambos. Aquí es un error de bus en un 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 

En otros sistemas operativos/compiladores De hecho, puede obtener una violación de segmento.

+0

Pensé que intentar escribir en la memoria de solo lectura causaría una segfault, no un error de bus? ¿O es eso específico del sistema operativo? – cHao

+0

¡He visto los dos! –

+0

Debes estar haciendo cosas alocadas por allí. :) La única vez que he visto un error de bus, la placa base era mala. – cHao

1

Las matrices de caracteres especificadas en el formulario "I am a good boy" son generalmente constantes; no puede modificarlas. Es por eso que tu primera variante falla. El segundo no, a medida que realiza una copia de datos y luego lo modifica.

6

Copiarlo al montón es una opción. Sin embargo, si lo que desea asignar un array local (pila), que puede hacer:

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

Entonces, la constante de cadena se copiarán en la pila.

0

char * str = "Soy un buen chico"; Tratar como literal e intentar modificarlo dará como resultado un error de bus. Es equivalente a const char * str = "Soy un buen chico", es decir, apunta a una cadena constante y no se permite modificar una cadena constante.

EDITAR: En el momento en que malloc() y copia está jugando con una copia de la cadena original y ptr no es del tipo 'const char *', en su lugar es 'char * ptr' y no se queja.

0

Compilar con C++ (g ++) muestra la desaprobación de asignar una cadena literal a un char * no constante que está diseñado para evitar este error:

[email protected]:~/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’ 

La advertencia relevante es en la línea 5.

Cambiar la declaración a const char * como se indica previene las asignaciones en la cadena literal.

Esta es también una lección sobre por qué no debe ignorar las advertencias.

Cuestiones relacionadas