2012-04-12 5 views
5

Sono molto nuovo a C e non riesco a capire cosa c'è che non va nel seguente codice.L'indirizzo 0x0 non è stack'd, malloc'd o (recentemente) free'd

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 mi sta dando questo errore:

==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 corrisponde alla linea che inizia con fputs verso la fine di questo codice.

Inoltre, mychars è una matrice bidimensionale che assomiglia a questo:

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

qualcuno può dirmi come risolvere questo problema? Inoltre, qualsiasi suggerimento su come dovrei migliorare il mio codice corrente (specialmente con malloc) sarebbe molto apprezzato.

Edit: Codice in 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 nuovo codice per str_replace, e principale

A scopo di verifica, ho sostituito il mio metodo str_replace con quella che si trova qui:

What is the function to replace string in C?

A ND mio principale è cambiato un po ':

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

ma sto ancora ricevendo

==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 

Forse la parte più frustrante di questo non è sapere cosa questi errori di lettura non validi sono.

EDIT 3 Ho aggiornato il codice al centro del ciclo for in quanto tale:

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

E ora sto iniziando a ottenere l'output! Tuttavia, dopo solo due iterazioni, ottengo un errore di segmentazione, con valgrind dandomi un sacco di questo:

==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 

risposta

5

In queste due linee

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

innanzitutto allocare spazio per result che poi sciolto immediatamente dopo sovrascrivendo il ritorno di str_replace.Questa funzione restituisce probabilmente 0, pertanto il tuo fputs non riesce.

BTW, non eseguire il ritorno di malloc, in C questo è superfluo e potrebbe nascondere il fatto che si è dimenticato di includere il prototipo.

Modifica: La tua funzione str_replace è completamente errata nella gestione della memoria. Non restituire mai il puntatore a una variabile locale, lo spazio non è valido dopo aver lasciato la funzione.

+0

Jens, grazie ma non ho ancora idea di come sistemarlo. Codice per str_replace sopra – varatis

+0

@varatis, per 'str_replace' vedi la mia modifica. Per la logica del tuo programma, ho difficoltà a capire cosa vuoi ottenere. Perché stai allocando qualcosa all'interno del loop che poi cancelli e dove utilizzeresti l'ultimo valore assegnato in 'fputs'? –

+0

Sto provando a leggere un file riga per riga, e per ogni riga, sostituire determinati caratteri di quella riga con stringhe specificate da mychars – varatis

0

Se NUM è 0, quindi result è inizializzata e può essere 0 per caso.

Non si stanno verificando i risultati delle chiamate su malloc(), quindi un errore può significare che si sta tentando di scrivere su un puntatore NULL.

Dove viene dichiarato mychars?

+0

Sono entrambi dichiarati in un file "mychars.h", che viene importato. Ma ho anche notato che questo funziona eccetto quando includo str_replace ... Vado avanti e aggiungo quel codice – varatis

+0

'malloc' restituendo' NULL' è molto raro oggigiorno, specialmente con i sistemi operativi che implementano il overcommitting della memoria . – dreamlax

+0

@dreamlax: wtf !? – James

0

Non mostrare come mychars dichiarato, ma questa linea:

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

sembra probabilmente assegna un solo byte. Inoltre stai allocando molta memoria e non la liberi mai. E qui:

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

si alloca memoria utilizzando malloc e quindi eliminare completamente il puntatore che la memoria assegnando il valore di ritorno di un'altra funzione sopra la parte superiore di esso.

+0

dreamlax, ancora una volta, grazie mille per il tuo aiuto, ma come posso correggerlo/modificarlo? – varatis