2016-03-30 16 views
0

ich ein Problem mit diesem Stück Code, das ich oft (aber der Fehler immer erschienen) geändert: Es scheint, es hat einen Fehler bei der Freigabe des letzten Index der „Filter“seltsam free() ungültiger Zeiger C

char** read_and_filter(int fd) { 
    char buf[MAXLENGTH]; 
    char **bufs=NULL; 
    char ch; 
    int j = 0, len = 0, t = 0; 
    while (!t && read(fd,&ch,1) == 1) { 
    switch (ch) { 
    case '\n': 
     t = 1; 
    case ' ': 
     bufs = realloc(bufs, (j+1)*sizeof(char*)); 
     bufs[j++] = strndup(buf,len); 
     memset(buf,0,len); 
     len = 0; 
     break; 
    default: 
     buf[len++] = ch; 
    } 
    } 
    bufs[j] = 0; 
    return bufs; 
} 

int main(int argc, char **argv) { 
    char **filter; 
    int i,fd = open("input.txt",O_RDONLY); 
    filter = read_and_filter(fd); 
    for(i = 0; filter[i]; i++) { 
    printf("%s\n",filter[i]); 
    free(filter[i]); 
    } 
    return 0; 
} 

Hier ist die Ausgabe:

0x1521030 
HOME 
0x1521050 
2 
0x1521070 
A 
0x1521010 
8 
0x15210c0 
D 
*** Error in `./test': free(): invalid pointer: 0x00000000015210c0 *** 

ich es auch mit valgrind zu debuggen versucht, (es sagt mir, dass der allocator 9 Byte, während die Summe der Zeichen zu befreien versucht, 8, seltsam oder?) und gdb aber nichts hat funktioniert. Die erste Zeile ist input.txt "HOME 2 A 8 D \ n"

+0

Variablennamen, die keinen Dokumentationswert haben, lassen Kätzchen weinen. 'j'? 't'? Ok, einfach genug, um sie herauszufinden, wenn man sich die Zeit nimmt, den Code zu lesen, aber man kann es mit vernünftiger Benennung leichter machen. Selbst wenn es Ihnen nicht darum geht, es einfacher zu machen, wenn Sie andere Menschen bitten, mit Ihrem Problem ohne Entschädigung zu helfen, sind Sie es ihnen schuldig, die Aufgabe für sie so einfach wie möglich zu machen. Darüber hinaus scheint Ihre Ausgabe nicht mit dem von Ihnen bereitgestellten Programm übereinzustimmen. Es gibt scheinbar vor jeder Zeichenfolge Zeigerwerte, die von Ihrem Code nicht angezeigt werden. – mah

+0

Diese Anweisungen verursachten beim Freigeben ein Problem - 'buf [len ++] = ch;'. Wenn Sie zu dem wechseln, auf was der Zeiger zeigt. – ameyCU

+2

@ameyCU Umm, nein, das ändert keine Zeiger in irgendeiner Weise –

Antwort

7

Das erste Mal, wenn diese Linien

bufs = realloc(bufs, (j+1)*sizeof(char*)); 
bufs[j++] = strndup(buf,len); 

Sie Speicher erhalten ausgeführt werden für 1 Zeiger (j 0 war). Dies läßt keinen Raum für die Schließung NULL Sie am Ende der Funktion schreiben mit

bufs[j] = 0; 

, so dass Sie über die zugewiesenen Speicher schreiben, haben also undefiniertes Verhalten. Jedes Mal, wenn Sie die Pufferlänge verlängern.

+0

Wenn ich nehme bufs [j] = 0 aus dem Fehler ist: 0x1a14030 HOME 0x1a14050 0x1a14070 A 0x1a14010 0x1a140c0 D 0x21 Segmentation Fault – JoAccount

+0

Sie müssen ein weiteres Element zuweisen, als Sie tun. 'realloc (bufs, (j + 2) * sizeof (char *))' –

+0

Sie müssen auch 'free (filter)' nachdem die Schleife ihre Elemente freigibt. –

6

Ihre bufs[j] = 0; am Ende von read_and_filter schreibt in nicht zugewiesenen Speicher. Sie nie realloc -ed Ihre bufs für das extra 0.

0

Speicherleck auftritt von zwei Stellen - strdup und die realloc

Eine Antwort ist eine anfängliche Zuweisung von Speicher für den Puffer in Haupt zu machen, malloc und dann einen Zeiger auf den zugewiesenen Speicher an die Funktion übergeben . Die Funktion kann dann den Puffer neu zuordnen und Daten darin kopieren.

Bei der Rückkehr von der Funktion kann main auf die Daten direkt vom Puffer zugreifen, da es einen gültigen Zeiger darauf hat, und kann dann diesen Speicher freigeben, bevor er geschlossen wird.

Laut Valgrind hat das folgende keine Speicherverlust.

void read_and_filter(int fd, char **bufs) { 
    char buf[100]; 
    char ch; 
    int j = 0, len = 0, t = 0; 
    while (!t && read(fd,&ch,1) == 1) { 
    switch (ch) { 
    case '\n': 
     t = 1; 
    case ' ': 
     *bufs = realloc(*bufs, (j + 2)*sizeof(char*)); 
     strncpy(bufs[j++], buf, len); 
     memset(buf,0,len); 
     len = 0; 
     break; 
    default: 
     buf[len++] = ch; 
    } 
    } 
    bufs[j] = 0; 
    return; 
} 

int main(int argc, char **argv) { 
    char *bptr = malloc(1); 
    int fd = open("input.txt", O_RDONLY); 

    read_and_filter(fd, &bptr); 

    printf("%s\n", bptr); 
    free(bptr); 
    return 0; 

Allerdings kann ich nicht sicher sein, dass diese vollständig die beabsichtigte Funktionalität des OP repliziert, aber das Gesamtkonzept mit den Speicherproblemen befasst.