Forum: PC-Programmierung free() führt zu Exception


von Robert B. (rsb89)


Lesenswert?

Hallo,

neues Problem neuer Beitrag...

Um eine Datei in einen String einzulesen alloziere ich Speicher mit 
malloc(). Wenn ich den Speicher mit free() am ende des Programms wieder 
freigeben möchte, springt das Programm (beim debuggen) in folgenden 
Handler:
1
/***
2
*void _unlock_fhandle(int fh) - unlock file handle
3
*
4
*Purpose:
5
*       Release the lock associated with passed file handle.
6
*
7
*Entry:
8
*       int fh  - CRT file handle
9
*
10
*Exit:
11
*
12
*Exceptions:
13
*
14
*******************************************************************************/
15
16
void __cdecl _unlock_fhandle (
17
        int fh
18
        )
19
{
20
        LeaveCriticalSection( &(_pioinfo(fh)->lock) );
21
}

Der entscheidende Code sieht so aus (alles dazwischen habe ich im 
Programm auskommentiert):
1
  input = fopen(INPUTFILE, "r");
2
  datasize = ftell(input);
3
  plaindata = (char *)malloc(datasize);
4
  fscanf(input, "%s", plaindata);
5
  fclose(input);
6
7
        free(plaindata);

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Robert B. schrieb:
> plaindata = (char *)malloc(datasize);
>   fscanf(input, "%s", plaindata);

fscanf schreibt am ende ein 0 Byte in den "String" so viel platz ist 
dort aber nicht.

du brauchst 1 Byte mehr speicher, außerdem würde ich read statt fscanf 
verwenden.

von Robert B. (rsb89)


Lesenswert?

Danke für den Hinweis! Leider löst das nicht mein Problem. Ich debugge 
Schritt für Schritt und erst wenn ich die Funktion free() erreiche 
springt das Programm in den Handler.

von Peter II (Gast)


Lesenswert?

Robert B. schrieb:
> Ich debugge
> Schritt für Schritt und erst wenn ich die Funktion free() erreiche
> springt das Programm in den Handler.

wenn du den Speicher überschreibt kann das Problem irgendwo auftauchen 
und nicht an eine genauen stelle.

von Robert B. (rsb89)


Lesenswert?

Peter II schrieb:
> wenn du den Speicher überschreibt kann das Problem irgendwo auftauchen
> und nicht an eine genauen stelle.

Kannst du das genauer beschreiben? Also klar, wenn ich den Speicher 
überschreibe gibt's Probleme. Aber in meinem Programm überschreibe ich 
doch nichts, oder?

von mh (Gast)


Lesenswert?

Hast du schonmal überprüft ob malloc überhaupt Speicher bereitstellt 
(plaindata != NULL)? Mein Tipp ist, dass ftell als Ergebnis 0 liefert, 
da du am Anfang der Datei stehst.

von Robert B. (rsb89)


Lesenswert?

Danke!!! Ja ich bekomme 0 von ftell. Damit ist der Rest natürlich Murks.

von Peter II (Gast)


Lesenswert?

Robert B. schrieb:
> Kannst du das genauer beschreiben? Also klar, wenn ich den Speicher
> überschreibe gibt's Probleme. Aber in meinem Programm überschreibe ich
> doch nichts, oder?

doch denke schon, denn mit %s liest man eine String ein und am ende wird 
ein 0 Byte eingefügt dafür hast du aber kein Platz mehr.

von Robert B. (rsb89)


Lesenswert?

Ja, du hast recht! So läuft es jetzt, wie es soll.
1
  input = fopen(INPUTFILE, "r");
2
  fseek(input, 0, SEEK_END);
3
  datasize = ftell(input);
4
  fseek(input, 0, SEEK_SET);
5
  plaindata = (char *)malloc(datasize+1);
6
  fscanf(input, "%s", plaindata);
7
  fclose(input);
8
9
  free(plaindata);

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

bitte verwende doch einfach read. fscan ist hier nicht sinnvoll, weil du 
ja die ganze Datei einlesen willst.

von Robert B. (rsb89)


Lesenswert?

1
  if(NULL == (input = fopen(INPUTFILE, "r")))
2
    input = make_file();
3
4
  fseek(input, 0, SEEK_END);
5
  datasize = ftell(input);
6
  fseek(input, 0, SEEK_SET);
7
  plaindata = (char *)malloc(datasize+1);
8
  fread(plaindata, sizeof(char), datasize, input);
9
  plaindata[datasize] = '\0';
10
  fclose(input);
11
12
  free(plaindata);

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wird calloc anstelle von malloc verwendet, ist der Speicher bereits 
Null-Initialisiert, und man kann das nachträgliche Setzen der '\0' nicht 
versehentlich vergessen:
1
  plaindata = (char *) calloc(datasize + 1, sizeof (char));
2
  fread(plaindata, sizeof (char), datasize, input);
3
4
  // kann wegfallen
5
  plaindata[datasize] = '\0';

von Udo S. (urschmitt)


Lesenswert?

Ich glaube die Ursache warum das erst beim free() zu einem Fehler führt 
ist daß im Debug Modus eine magic number hinter den allozierten 
Speicherblock gepackt wird und free das prüft und dabei den 
Überschreiber bemerkt.

von Peter II (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Wird calloc anstelle von malloc verwendet, ist der Speicher bereits
> Null-Initialisiert, und man kann das nachträgliche Setzen der '\0' nicht
> versehentlich vergessen:
>   plaindata = (char *) calloc(datasize + 1, sizeof (char));
>   fread(plaindata, sizeof (char), datasize, input);
>
>   // kann wegfallen
>   plaindata[datasize] = '\0';

finde ich aber hierfür nicht sinnvoll. Es nur Resourcenverschwendung, da 
der Speicher danach eh mit Inhalt gefüllt wird.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.