2012-04-12 14 views
5

Soy muy nuevo en C, y parece que no puede encontrar lo que está mal con el siguiente código.Dirección 0x0 no está apilado, malloc o (recientemente) ha sido libre

int main() { 
    char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, cgichars[i][1]); 
       result = (char *) malloc (sizeof(char) * 128); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

Valgrind me está dando este error:

==4266== Invalid read of size 1 
==4266== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==4266== by 0x5118A8D: fputs (iofputs.c:37) 
==4266== by 0x400A0F: main (repl.c:35) 
==4266== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

repl.c corresponde a la línea que empieza fputs hacia el final de este código.

Además, mychars es una matriz bidimensional que tiene este aspecto:

char *mychars[NUM][2] = { 
    "a", "97", 
    "b", "98", 
    .... 

¿Puede alguien decirme cómo solucionar este problema? Además, cualquier sugerencia sobre cómo debería mejorar mi código actual (especialmente con malloc) sería muy apreciado.

Editar: Código de str_replace

char *str_replace(char *str, char *orig, char *rep) { 
    char buffer[4096]; 
    char *p; 

    if(!(p = strstr(str, orig))) 
    return NULL; 

    strncpy(buffer, str, p-str); 
    buffer[p-str] = '\0'; 
    sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); 

    return buffer; 

} 

EDIT 2 Nuevo Código de str_replace y principal

Para propósitos de prueba, he reemplazado mi método str_replace con la que se encuentra aquí:

What is the function to replace string in C?

Un nd mi principal se cambia ligeramente:

int main() { 
    static const char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, mychars[i][1]); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

Pero sigo teniendo

==6730== Invalid read of size 1 
==6730== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==6730== by 0x5118A8D: fputs (iofputs.c:37) 
==6730== by 0x400995: main (repl.c:29) 
==6730== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

Tal vez la parte más frustrante de esto es no saber lo que estos errores de lectura son válidos.

EDITAR 3 He actualizado el código en el centro del bucle for como tal:

 int i; 
     char* result; 
     result = &line[0]; 
     for(i=0; i< NUM_CGICHARS;i++) 
     { 
      char *rep; 
      rep = (char *) malloc (sizeof(char)); 
      strcpy(rep, cgichars[i][1]); 
      char *with; 
      with = (char *) malloc (sizeof(char)*3); 
      strcpy(with, cgichars[i][0]); 
      result = str_replace(result, rep, with); 
      fputs(result, stdout); 
      free(rep); 
      free(with); 
     } 

y ahora estoy empezando a obtener una salida! Sin embargo, después de sólo dos iteraciones, me sale un error de segmentación, con valgrind darme un manojo entero de esto:

==9130== Invalid read of size 1 
==9130== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==9130== by 0x5118A8D: fputs (iofputs.c:37) 
==9130== by 0x4009DF: main (teststep1.c:27) 
==9130== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

Respuesta

5

En estas dos líneas

  result = (char *) malloc (sizeof(char) * 128); 
      result = str_replace(line, rep, with); 

asignar espacio para la primera result que, a continuación suelta inmediatamente después sobrescribiéndolo con el regreso de str_replace.Esa función probablemente devuelve 0, por lo que su fputs falla.

Por cierto, no eche el retorno de malloc, en C esto es superfluo y puede ocultar el hecho de que olvidó incluir el prototipo.

Edit: Su función str_replace es completamente incorrecta en su manejo de memoria. Nunca devuelva el puntero a una variable local, el espacio no es válido después de que haya abandonado la función.

+0

Jens, gracias, pero todavía no tengo ni idea de cómo solucionar esto. Código para str_replace arriba de – varatis

+0

@varatis, para 'str_replace' ver mi edición. Para la lógica de su programa, me es difícil entender lo que quiere lograr. ¿Por qué estás asignando algo dentro del ciclo que luego borras, y donde solo usarías el último valor asignado en los 'fputs'? –

+0

Estoy tratando de leer un archivo línea por línea, y para cada línea, reemplazar ciertos caracteres de esa línea con cadenas especificadas por mychars – varatis

0

Si NUM es 0, entonces result es inicializado y puede haber 0 por casualidad.

No está verificando los resultados de sus llamadas a malloc(), por lo que una falla puede significar que está tratando de escribir en un puntero NULL.

¿Dónde se declara mychars?

+0

Ambos se declaran en un archivo "mychars.h", que se importa. Pero también he notado que esto funciona, excepto cuando incluyo str_replace ... Voy a seguir adelante y agrego ese código – varatis

+0

'malloc' regresando' NULL' es muy raro en estos días, especialmente con los sistemas operativos que implementan la memoria overcommitting . – dreamlax

+0

@dreamlax: wtf !? – James

0

No mostrar cómo mychars se declara, pero esta línea:

rep = (char *) malloc (sizeof(mychars[i][0])) 

parece que probablemente sólo asigna un byte. También está asignando mucha memoria y nunca la libera. Y aquí:

result = (char *) malloc (sizeof(char) * 128); 
result = str_replace(line, rep, with); 

asignar memoria utilizando malloc y luego se descarta por completo el puntero a la memoria asignando el valor de retorno de otra función en la parte superior de la misma.

+0

dreamlax, de nuevo, muchas gracias por su ayuda, pero ¿cómo puedo arreglar/cambiar esto? – varatis

Cuestiones relacionadas