2010-12-09 20 views
1

Ich bin ein bisschen verwirrt.Seltsame Änderung im Programm bei der Verwendung von free()

Ich schreibe ein sehr einfaches Dateisystem, das im Grunde:
Liest in einem Block von Daten aus einer Datei
-gets ein Hash aus diesem Block
-Suche eine verknüpfte Liste für diesen Hash
-wenn nicht gefunden,
-wenn gefunden hängen, nichts tun

das Problem: (wahrscheinlich undicht)
Wenn ich nicht frei verwenden, das Programm viel langsamer ist.

Wenn ich kostenlos benutze, läuft das Programm schneller, endet mit Blockgrößen von 128 und 256, stürzt aber ab, wenn ich 512 versuche (stürzt im Einfügevorgang ab). Ich arbeite in Visual Studios und es stürzt einfach ab. Ich bekomme die Meldung "VS stoppte funktioniert ..", die keinen Einblick bietet.

Obendrein bekomme ich viel andere Ergebnisse, wenn ich freie vs. verwende, wenn ich es nicht verwende.

Jede Hilfe würde sehr geschätzt werden.

Okay, einige Code (kurz):

struct list_el 
{ 
    char* hash; 
    struct list_el* next; 
    struct list_el* prev; 
}; 
typedef struct list_el item; 

item* head, *tail; 

void ins(item* ins) 
{ 
item* iterator = (item*)malloc(sizeof(item)); 
if(iterator == NULL) 
{ 
    printf("out of memory\n"); 
    exit(1); 
} 
else if(head != NULL) 
{ 
    iterator = head; 
    while(iterator != NULL) 
    { 
     if(strcmp(iterator->hash, ins->hash) == 0) 
     { 
      //free(iterator); (problem line) 
      matches++; 
      return; 
     } 
     else if(iterator->next != NULL) 
      iterator = iterator->next; 
     else 
      break; 

    } 
} 

unique_blocks++; 
if(head == NULL) 
{ 
    head = ins; 
    ins->prev = NULL; 

} 

else 
{ 
    tail->next = ins; 
    ins->prev = tail; 
} 

tail = ins; 
ins->next = NULL; 
} 


int main() 
{ 
unsigned char* c = (unsigned char*)malloc(BLOCKSIZE+1); 
if(c == NULL) 
    exit(1); 
FILE* fp = fopen("input2","r"); 
if(fp == NULL) 
    exit(1); 
int i = 0; 

char* answer = (char*)malloc(sizeof(char)*90); 
if(answer == NULL) 
    exit(1); 
item* ins_item; 
char ch; 
do 
{ 
    if(i == BLOCKSIZE) 
    {  
     i = 0; 
     answer = sha1((unsigned char*)c); 
     ins_item = (item*)malloc(sizeof(item)); 
     if(ins_item == NULL) 
      exit(1); 
     ins_item->hash = answer; 
     ins(ins_item); 

    } 
    else 
    { 
     ch = fgetc(fp); 
     bytes_read++; 
     c[i] = ch; 
     i++; 
    } 
}while(ch != EOF); 
fclose(fp); 
return 0; 
} 

Antwort

6

In Ihrer ins() Funktion Sie:

  • malloc() Speicher und verwenden iterator, um es später

  • einige Aussagen zu Punkt Sie tun iterator = head, was bedeutet, dass Sie den Zeiger auf den zugewiesenen Speicherbereich verloren haben und haben ein Hauptspeicherleck

  • dann ein paar Aussage nach, dass Sie tun/nicht (je nach Kommentar) free() das Element an dem Iterator zeigte, während es noch in Ihrer Liste ist, während Sie wahrscheinlich kostenlos wollten der Bereich von malloc()

EDIT:

Warum weisen Sie Speicher für den Iterator? In der Regel sind Listen-Iteratoren einfache Zeiger, die genau auf das verweisen, was der Code gerade untersucht.

EDIT 2:

Der Absturz wird höchstwahrscheinlich von Ihrem Programm den Zugriff befreit (und damit anavailable) Speicher verursacht, die nach wie vor Teil der Liste ist.

Freigegebener Speicher wird nicht unbedingt an das System zurückgegeben. Abhängig davon, wie der Heap-Allokator funktioniert, könnte er sogar über einen anderen malloc()-Aufruf wieder Ihrem Programm zugeordnet werden. Wenn Ihr Programm versucht, erneut darauf zuzugreifen, könnte es sehr unterschiedliche Daten als erwartet haben.

Zwei weitere Punkte:

  • Halten Sie Ihre Identifikatoren eindeutig innerhalb des gleichen Umfang.Es kann den Compiler nicht stoppen, aber es bringt das menschliche Gehirn sicher zum Stillstand. Z.B. Sie sollten keine ins() Funktion mit einem ins Parameter haben.

  • Visual Studio hat einen Debugger, der (mir wurde gesagt) ist ziemlich gut. Lernen, wie man es benutzt, würde einem Los helfen.

0

auch, warum tun Sie:

while(iterator != NULL) 
{ 
    if(strcmp(iterator->hash, ins->hash) == 0) 
    { 
     //free(iterator); (problem line) 
     matches++; 
     return; 
    } 
    else if(iterator->next != NULL) 
     iterator = iterator->next; 
    else 
     break; 

} 

Diese funktional äquivalent zu:

while(iterator != NULL) 
{ 
    if(strcmp(iterator->hash, ins->hash) == 0) 
    { 
     //free(iterator); (problem line) 
     matches++; 
     return; 
    } 

    iterator = iterator->next; 
} 

Aber Ihre Version ist länger und wahrscheinlich später Fehler zu entwickeln.

+0

guten Punkt. Vielen Dank. – prelic

Verwandte Themen