realloc und heap corruption problem

The_Rave

Mitglied

Ich schreibe gerade an einem Plugin für Winamp. Es ist also eine dll. Hab hier ein Problem mit dem Heap und keinen Plan was da falsch sein kann. Vielleicht kann ja mal einer rüber kucken. Es gibt da auch noch ein main.cpp, was diese cpp Datei mit dieser Funktion aufruft. Es sind .cpp Dateien weil ich es vorher mit der String Klasse realisiert hab. Ich wollte aber trotzdem mal ausprobieren wie man das mit char*, malloc und konsorten hinbekommt.

Es funktioniert eigentlich soweit alles, der cAllBuf Buffer wird mit dem Inhalt der heruntergeladenen URL gefüllt, aber am Ende der Funktion kommt es zu einer Heap corruption.

Code:
#include <cstdlib>

//For Wininet.h we need Windows.h
#include <Windows.h>
#include <Wininet.h>

int download(char *cURL)
{
 HINTERNET hInternet;
 HINTERNET hFile;
 char Buf[1025];
 string webSiteBuf;
 char *cAllBuf;
 string sToken;
 DWORD ReadSize;
 BOOL bResult;

 hInternet = InternetOpen(
            "WININET Sample Program",
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,
            NULL,
            0);

 hFile = InternetOpenUrl(
            hInternet,
            cURL,
            NULL,
            0,
            INTERNET_FLAG_RELOAD,
            0);

 //Minimalspeicher reservieren und mit 0 initialisieren
 cAllBuf = (char *) calloc (1,sizeof(char));
 
 //wenn Internetverbindung vorhanden
 if (hFile)
  {
   for(int i=1;;i++)
    {
     //Lesen von 1024 Bytes
     ReadSize = 1024;

     bResult = InternetReadFile(
                hFile,
                Buf,
                1024,
                &ReadSize);

     if(bResult && (ReadSize == 0)) break;
     
	 //Ende im Buf bei [1024] markieren
         Buf[ReadSize] = '\0';

	 //Speicher vergrößern und neuen Wert hinzukopieren
	 cAllBuf = (char *) realloc (cAllBuf, sizeof(char)*((ReadSize*i)+1));
	 strcat(cAllBuf,Buf);
    }//for ende

   //Verbindung beenden
   InternetCloseHandle(hFile);
   InternetCloseHandle(hInternet);
 }
 free(cAllBuf);
 return 0;
}

Das Problem ist die Funktion strcat(cAllBuf,Buf), wenn ich zum Beispiel strcat(cAllBuf,"Test") eingebe läuft alles durch. Hier sind noch die Debugger Meldungen:

'
Code:
winamp.exe': Loaded 'C:\WINDOWS\system32\hnetcfg.dll', No symbols loaded.
'winamp.exe': Loaded 'C:\WINDOWS\system32\wshtcpip.dll', No symbols loaded.
Heap corruption detected at 03ABB360
First-chance exception at 0x7c92b56d in winamp.exe: 0xC0000005: Access violation writing location 0x61627326.
First-chance exception at 0x7c81eb33 in winamp.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00b0edb0..
Heap corruption detected at 03ABB360
First-chance exception at 0x7c959fd3 in winamp.exe: 0xC0000005: Access violation reading location 0x61627326.
First-chance exception at 0x7c81eb33 in winamp.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00b0e714..
First-chance exception at 0x7c81eb33 in winamp.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
Unhandled exception at 0x7c81eb33 in winamp.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00b0e714..

Ist das eigentlich normal das bei jedem Schleifendurchlauf der cAllBuf eine neue Adresse bekommt? Dachte eigentlich das der Speicher nur vergrößert wird. Und ist das richtig, daß ich immer die neue Endgröße bei realloc angeben muss, nicht nur eine Addition zur bisherigen Größe?
 
Zuletzt bearbeitet:

The_Rave

Mitglied
So ich hab jetzt nochmal den Buffer der String Version verglichen mit dem Buffer der Char Version und festgestellt daß mir in der Char Version 10 Zeilen HTML Code fehlten. Außerdem waren da noch ein paar Zeichen mit Buchstabensalat dazwischen. Da das ganze ziemlich zum Schluss der Seite war und zu Anfang alles stimmte hab ich dann die Zeile:
Code:
cWebSiteBuf = (char *) realloc (cWebSiteBuf, sizeof(char)*((ReadSize*i)+1));

in 

cWebSiteBuf = (char *) realloc (cWebSiteBuf, sizeof(char)*((1024*i)+1));

geändert. Im letzten Schleifendurchlauf war die ReadSize nämlich nur noch 719.

Und da scheint das Problem zu liegen: mit cAllBuf = (char *) realloc (cAllBuf, sizeof(char)*((ReadSize*i)+1)); definierte ich den Buffer im 6 Schleifendurchgang also wieder kleiner als er im 5. Durchgang war und als ich es eigentlich brauchte.

Speicher für 1024*5+1=5121 Zeichen im 5 Schleifendurchlauf...
Speicher für 719*6+1=4314 Zeichen hatte ich im sechsten Durchgang zur Verfügung, dann wurde kopiert und später am Ende der ganzen Funktion gabs das den korrupten Heap.

Speicher für 1024*5+1+ 719+1=5895 Zeichen wären also das minimum...