2016-08-31 5 views
1

verwenden, so habe ich noch eine neue Frage für Sie. Diese Funktion soll alle Bytes aus einer übergebenen Datei lesen, sie im Heapspeicher speichern und dann die Adresse im übergebenen 'content'-Parameter und die Länge im übergebenen' length'-Parameter speichern.Warum nicht kostenlos() in diesem Fall

bool load(FILE* file, BYTE** content, size_t* length) 
{ 
if (file == NULL) 
{ 
    return false; 
} 

//array to hold the bytes?? 
BYTE* buffer = malloc(sizeof(BYTE)); 

//To hold the number of bytes currently loaded 
size_t size = 0; 


//Pointer to keep track of where I am adding the data to in buffer 

//get all the bytes from the file and put them in the buffer 
for(int i = fgetc(file); i != EOF; i = fgetc(file)) 
{ 
    buffer[size] = (char) i; 
    size++; 
    buffer = realloc(buffer, size + 1); 
} 

//dereference length 
*length = size; 

//derefernce content 
*content = buffer; 

//free(buffer); 
return true; 
} 

So zuvor das größere Programm, das diese Funktion ein Teil war nicht funktioniert, aber wenn ich aus dem

free(buffer); 
kommentiert

Anruf am Ende meines Programm gestartet perfekt zu arbeiten. Ich war motiviert, dies zu kommentieren, als ich auf einen doppelten kostenlosen Fehler stieß. Meine Frage ist also: Warum verursacht das Freigeben in diesem Fall einen Fehler?

Meine Intuition sagt mir, dass es ist, weil die Daten, dass

*content 

Punkte wird nun als „gelöscht“ und so wurde mein Programm funktioniert nicht. Irgendwann später im Code gebe ich auch den Inhalt frei *, woher kommt der doppelte freie Fehler. Aus irgendeinem Grund bin ich jedoch geneigt zu glauben, dass die Daten nicht wirklich "gelöscht" werden.

Tut mir leid, wenn dies eine Menge ist, habe ich verwirrt durch Speicherzuteilung, frei, und Zeiger für eine Weile und versuche, ein tieferes Verständnis zu gewinnen.

+2

Nur eine Anmerkung.Ihre Zuweisung durch wiederholtes Aufrufen von 'realloc' für jedes aus der Datei gelesene Zeichen ist die ineffizienteste Verwendung von' realloc', die Sie sich ausdenken können. Ordnen Sie stattdessen eine vernünftige Anzahl von Bytes zu (zB '1024',' 4096' oder mehr) und behalten Sie dann einen Index und lesen Sie Zeichen aus der Datei, bis der Index ('+ 1') Ihr ursprüngliches Limit erreicht, dann rufen Sie' realloc auf 'und zuteilen ein anderes' 4096' usw. und wiederholen. Wie viele Aufrufe von 'realloc' machen Sie mit einer 1-Megabyte-Datei? –

+0

Was David gesagt hat ... Oder verdoppeln Sie die Menge an zugewiesenem Speicherplatz bei jedem Aufruf von 'realloc()' - optional eine abschließende Schrumpfung 'realloc()', wenn zu viel zusätzlicher Platz übrig ist (zB wenn mehr als 1 KiB vorhanden sind) von ungenutztem Raum). –

+0

@ DavidC.Rankin die innere Arbeit der 'Realloc'-Funktion wird nur diese Überprüfung zu tun und dann eine andere Funktion aufrufen, wenn die aktuelle Kapazität überschritten wird, so würde ich argumentieren, dass es unnötigerweise verkompliziert OP-Code, um diese Prüfungen aufzuheben . Wahrscheinlich liefert das OS Blöcke von mindestens einigen Kilobyte. –

Antwort

4

Wenn Sie Speicher (oder Ressourcen im Allgemeinen) zuweisen, müssen Sie sicherstellen, dass Sie eine eindeutige Besitzersemantik haben. Wem gehört die zugewiesene Ressource und ist verantwortlich für deren Freigabe?

Für eine Funktion, die Ressourcen zuweist, ist eine vernünftige Semantik, dass die Funktion die zugewiesene Ressource zurückgibt, wenn sie erfolgreich ist, und sofern nicht anders angegeben, besitzt der Aufrufer diese Ressource. Wenn die Funktion fehlschlägt, sollte der Aufrufer keine Bereinigung durchführen müssen.

Ihre load() Funktion weist einen Puffer zu. Während der meisten seiner Funktion Körper, load() besitzt diesen Puffer. Kurz bevor es Erfolg zurückgibt, überträgt es effektiv Besitz dieses Puffers an den Aufrufer (über das Ausgabeargument content). Wenn load() nach dem Zuordnen des Puffers einen Fehlerpunkt hatte, sollte er free(buffer) entlang diesem Fehlerpfad aufrufen.


Ich fühle mich auch gezwungen, ein paar Probleme mit Ihrem Code zu hinweisen:

BYTE* buffer = malloc(sizeof(BYTE)); 

Sie sollten prüfen, ob malloc ausfällt. Darüber hinaus ist sizeof (BYTE) nicht sinnvoll, da es per definitionem 1.

buffer = realloc(buffer, size + 1); 

Diese schlechte Praxis ist. Wenn realloc fehlschlägt, werden Sie den alten Wert von buffer verlieren und Speicher verlieren. Es ist besser zu tun:

BYTE* tmp = realloc(buffer, size + 1); 
if (tmp == NULL) 
{ 
    free(buffer); 
    return false; 
} 
buffer = tmp; 

Schließlich wächst Ihr Puffer um 1 Byte jedes Mal ist sehr ineffizient. Typischer wäre es, die Puffergröße zu verdoppeln oder um ein Vielfaches zu vergrößern.

Verwandte Themen