¿Por qué este código C de inversión de cadenas provoca un error de segmentación? [duplicar]

Resuelto james asked hace 14 años • 8 respuestas

Estoy tratando de escribir código para invertir una cadena en su lugar (solo estoy tratando de mejorar en la programación en C y la manipulación de punteros), pero no puedo entender por qué recibo un error de segmentación :

#include <string.h>

void reverse(char *s);

int main() {
    char* s = "teststring";
    reverse(s);

    return 0;
}

void reverse(char *s) {
    int i, j;
    char temp;

    for (i=0,j = (strlen(s)-1); i < j; i++, j--) {
        temp = *(s+i);     //line 1
        *(s+i) = *(s+j);   //line 2
        *(s+j) = temp;     //line 3
    }
}

Son las líneas 2 y 3 las que están causando la falla de segmentación. Entiendo que puede haber mejores formas de hacer esto, pero estoy interesado en descubrir qué está causando específicamente el error de segmentación en mi código .

Actualización : he incluido la función de llamada según lo solicitado.

james avatar Oct 24 '09 00:10 james
Aceptado

No hay forma de saberlo solo con ese código. Lo más probable es que esté pasando un puntero que apunta a una memoria no válida, una memoria no modificable o algún otro tipo de memoria que simplemente no se puede procesar de la forma en que la procesa aquí.

¿Cómo llamas a tu función?

Agregado: está pasando un puntero a una cadena literal. Los literales de cadena no son modificables. No se puede revertir una cadena literal.

En su lugar, pase un puntero a una cadena modificable

char s[] = "teststring";
reverse(s); 

Esto ya se ha explicado hasta la muerte aquí. "teststring"es un literal de cadena. El literal de cadena en sí es un objeto no modificable. En la práctica, los compiladores podrían (y lo harán) ponerlo en memoria de sólo lectura. Cuando inicializas un puntero como ese

char *s = "teststring";

el puntero apunta directamente al comienzo de la cadena literal. Cualquier intento de modificar lo sseñalado se considerará fracasado en caso general. Puedes leerlo, pero no puedes escribir en él. Por este motivo, se recomienda encarecidamente señalar cadenas literales con variables de puntero a constante únicamente.

const char *s = "teststring";

Pero cuando declaras tu scomo

char s[] = "teststring";

obtienes una matriz completamente independiente subicada en la memoria modificable ordinaria, que simplemente se inicializa con una cadena literal. Esto significa que esa matriz modificable independiente sobtendrá su valor inicial copiado del literal de cadena. Después de eso, su smatriz y el literal de cadena continúan existiendo como objetos completamente independientes. El literal aún no es modificable, mientras que su smatriz sí lo es.

Básicamente, la última declaración es funcionalmente equivalente a

char s[11];
strcpy(s, "teststring");
AnT stands with Russia avatar Oct 23 '2009 17:10 AnT stands with Russia

Su código podría tener errores de segmentación por varias razones. Aquí están los que me vienen a la mente.

  1. s es NULO
  2. s apunta a una cadena constante que se mantiene en la memoria de solo lectura
  3. s no tiene terminación NULL

Creo que el número 2 es el más probable. ¿Puedes mostrarnos el sitio de llamada de reversa?

EDITAR

Según su muestra, la número 2 es definitivamente la respuesta. Un literal de cadena en C/C++ no es modificable. El tipo correcto es realmente const char*y no char*. Lo que debes hacer es pasar una cadena modificable a ese búfer.

Ejemplo rápido:

char* pStr = strdup("foobar");
reverse(pStr);
free(pStr);
JaredPar avatar Oct 23 '2009 17:10 JaredPar