Heap Block bei delete[]



  • Hallo,
    Ich habe ein kleines Problem beim wieder Freisetzen von dynamisch angelegtem Speicher.

    Ich schreibe ein kleines Programm, welches mir ermöglicht, Dateien zu verschlüsseln und vor anderen zu sichern, doch irgendwie will es mir den belegten Speicher nicht wieder freigeben.
    Hab schon sämtliche mir einfallende Suchmaschinen bemüht, doch leider habe ich nichts aussagekräftiges gefunden...

    Beim Aufruf des delete[] Operators kommt beim Debuggen nur die Meldung:

    HEAP[Merge.exe]: Heap block at 00B40FE0 modified at 00B5C601 past requested size of 1b619
    

    Hier ein kleiner Ausschnitt meines Codes:

    void CMergeDlg::WriteResource(std::vector<RESOURCE> & vec, const char *szRoot, char cData, int nHead, int nBody, int nCount)
    {
            // einige initialisierungen...
    
    	char *pHead = new char[sizeof(BYTE)+sizeof(bool)+sizeof(int)];
    	char *pHeader = new char[nHead];
    	char *pBody = new char[nBody];
    	ZeroMemory(pBody,nBody);
    	ZeroMemory(pHeader,nHead);
    
            // füllen des char arrays mit Daten
    
    	CFile fOut;
    	fOut.Open(dir,CFile::modeCreate | CFile::modeWrite);
    	Log("Writing file...");
    	fOut.Write(pHead,sizeof(BYTE)+sizeof(bool)+sizeof(int));
    	fOut.Write(pHeader,nHead);
    	fOut.Write(pBody,nBody);
    	fOut.Flush();
    	fOut.Close();
    
    	delete[] pHeader; // hier kommt die Meldung
    	delete[] pHead;
    	delete[] pBody;
    
    	Log("Done...");
    }
    

    Bin für jede Hilfe dankbar 🙂

    Mfg.



  • ich kann gerade nichts falsches sehen an deinem codeauschnitt, aber wieso nimmst du nicht für alles einen vector? dann hättest du das problem nicht. und was ist CFile?? nimm doch std::ofstream



  • vario-500 schrieb:

    ich kann gerade nichts falsches sehen an deinem codeauschnitt, aber wieso nimmst du nicht für alles einen vector? dann hättest du das problem nicht. und was ist CFile?? nimm doch std::ofstream

    Ich benutze CFile, da ich damit keinen formatierten Text schreibe und ich eh eine MFC Anwendung schreibe, wo CFile implementiert ist.

    Du meinst einen char vector wo ich jedes Byte reinschreibe und dann beim schreiben durchiteriere und jedes Byte einzeln schreibe?

    Ich glaub, dass das ziemlich an der Performance des Programms zerrt, das werde ich wohl als Endlösung nehmen, weil es ziemlich doof ist, dem Arbeitsspeicher beim überlaufen zuzugucken 😞



  • Der Fehler wird wohl da im ausgelassenen Code sein:

    // füllen des char arrays mit Daten
    

    Du weißt, dass bei Arrays von 0 bis Länge-1 gezählt wird?



  • manni66 schrieb:

    Der Fehler wird wohl da im ausgelassenen Code sein:

    // füllen des char arrays mit Daten
    

    Du weißt, dass bei Arrays von 0 bis Länge-1 gezählt wird?

    Jap, die Länge des Arrays müsste richtig sein, die Dateien werden ja richtig verschlüsselt.
    Hier mal der Teil dazwischen, falls euch das irgendwie weiterhilft.
    Bin hier echt am verzweifeln..

    int nCurPos = 0;
    	int nBodyPos = 0;
    	bool bEncryption = true;
    	memcpy(&pHead[nCurPos],&byEnc,sizeof(BYTE));nCurPos+=sizeof(BYTE);
    	memcpy(&pHead[nCurPos],&bEncryption,sizeof(bool));nCurPos+=sizeof(bool);
    	memcpy(&pHead[nCurPos],&nHead,sizeof(int));
    	nCurPos = 0;
    	memcpy(&pHeader[nCurPos],szVersion,7); nCurPos += 7;
    	memcpy(&pHeader[nCurPos],&nCount,sizeof(short)); nCurPos += sizeof(short);
    	memcpy(&pHeader[nCurPos],&nDir,sizeof(int));nCurPos+=sizeof(int);
    	memcpy(&pHeader[nCurPos],szRoot,nDir);nCurPos+=nDir;
    
    	int nPos = nHead+sizeof(BYTE)+sizeof(bool)+sizeof(int);
    	Log("Merging files");
    	m_pProgress.SetRange(0,vec.size());
    	m_pProgress.SetPos(0);
    	for(int i = 0; i < vec.size(); ++i)
    	{
    		RESOURCE *pRes = &vec.at(i);
    		char *szPath = new char[_MAX_PATH];
    		strcpy(szPath,szRoot);
    		strcat(szPath,pRes->szFileName);
    
    		if(!fIn.Open(szPath,CFile::modeRead))
    			continue;
    		char *szContent = new char[fIn.GetLength()];
    		ZeroMemory(szContent,fIn.GetLength());
    		fIn.Read(szContent,fIn.GetLength());
    
    		memcpy(&pHeader[nCurPos],&pRes->nFileName,sizeof(short));nCurPos += sizeof(short);
    		memcpy(&pHeader[nCurPos],pRes->szFileName,pRes->nFileName);nCurPos+=pRes->nFileName;
    		memcpy(&pHeader[nCurPos],&pRes->nFileLength,sizeof(int));nCurPos+=sizeof(int);
    		memcpy(&pHeader[nCurPos],&pRes->nFileTime,sizeof(int));nCurPos+=sizeof(int);
    		memcpy(&pHeader[nCurPos],&nPos,sizeof(int));nCurPos+=sizeof(int);
    		nPos += pRes->nFileLength;
    		memcpy(&pBody[nBodyPos],szContent,pRes->nFileLength);nBodyPos+=pRes->nFileLength;
    		m_pProgress.SetPos(i+1);
    
    		delete[] szContent;
    	}
    	Log("Done...");
    	pHeader[nHead] = 0;
    	pBody[nBody] = 0;
    
    	Log("Crypting files");
    	for(int i = 0; i < nHead; ++i)
    		pHeader[i] = Encryption(pHeader[i],byEnc);
    	for(int i = 0; i < nBody; ++i)
    		pBody[i] = Encryption(pBody[i],byEnc);
    	Log("Done...");
    


  • Gast351353546346346 schrieb:

    pHeader[nHead] = 0;
    	pBody[nBody] = 0;
    

    Fehler grad selber gefunden, echt doofe Sache. Das weg und schon gibt er den Speicher ordnungsgemäß frei...

    Vielen Dank für eure Hilfe



  • also ich weiß nicht genau was du da rum frickelst, aber das sieht echt grausig aus. probier es mal mit nem vector<char> und ich wette mit dir, dass du keine (großen) performance verlusste hast 😃

    Edit: seit wann kann man std::ofstream nur formatierten text schreiben??? ich würde versuchen, immer so standardkonform wie möglich zu bleiben. vielleicht soll dein programm auch mal auf nem anderen betriebssystem laufen.



  • Vielleicht ist ja noch nicht Hopfen und Malz verloren: Versuche doch std::vector oder std::string zu benutzen und vermeide memcpy oder strcat.



  • vario-500 schrieb:

    Edit: seit wann kann man std::ofstream nur formatierten text schreiben??? ich würde versuchen, immer so standardkonform wie möglich zu bleiben. vielleicht soll dein programm auch mal auf nem anderen betriebssystem laufen.

    Ich habe mich da strikt an msdn gehalten, da sollte ja was richtiges stehen o.O
    http://msdn.microsoft.com/de-de/library/60fh2b6f(v=vs.80).aspx

    knivil schrieb:

    Vielleicht ist ja noch nicht Hopfen und Malz verloren: Versuche doch std::vector oder std::string zu benutzen und vermeide memcpy oder strcat.

    Was ist denn so falsch daran? :o



  • Gast351353546346346 schrieb:

    Was ist denn so falsch daran? :o

    Möglicherweise (Ich hab mir den Code nicht so genau angesehen) ist dein Code zwar korrekt, aber stilistisch ist er leider schrecklich.



  • Beispiel: Du kopierst deinen Header in einen Speicherbereich. Diesen Speicherbereich schreibst du in die Datei. Warum schreibst du denn nicht gleich in die Datei?

    Was ist denn so falsch daran?

    Ein Hort fuer viele Fehlermoeglichkeiten. Auch ist es am besten, schlechte Angewohnheiten gleich im Keim zu ersticken.

    Gast351353546346346 schrieb:

    pHeader[nHead] = 0;
    	pBody[nBody] = 0;
    

    Hier zum Beispiel: std::vector hat eine Methode at. Genauso wie [], prueft aber ob die Arraygrenzen ueberschritten wurden und wirft notfalls eine Exception. Vielleicht hat VS ja das auch fuer den []-Operator.



  • knivil schrieb:

    Beispiel: Du kopierst deinen Header in einen Speicherbereich. Diesen Speicherbereich schreibst du in die Datei. Warum schreibst du denn nicht gleich in die Datei?

    Was ist denn so falsch daran?

    Ein Hort fuer viele Fehlermoeglichkeiten. Auch ist es am besten, schlechte Angewohnheiten gleich im Keim zu ersticken.

    Gast351353546346346 schrieb:

    pHeader[nHead] = 0;
    	pBody[nBody] = 0;
    

    Hier zum Beispiel: std::vector hat eine Methode at. Genauso wie [], prueft aber ob die Arraygrenzen ueberschritten wurden und wirft notfalls eine Exception. Vielleicht hat VS ja das auch fuer den []-Operator.

    Jo das hört sich echt böse an...
    Aber wie crypte ich denn direkt nen int Wert?
    Die Funktion gibt ja nen unsigned char zurück und nimmt ebenfalls nen unsigned char.
    Aber ansich ist die Idee super, das direkt zu schreiben anstatt zwischenzuspeichern



  • Auf dem ersten Blick hast Du noch ein Problem mit der Zeile 20:

    char *szPath = new char[_MAX_PATH];
    

    Dieser Block lebt wohl ewig? Und was passiert im Fall von continue? Fragen über Fragen 😉 🙂
    Weiterhin checke ich die Zeilen 4-6 nicht bzw. ihren Sinn. Du kopierst da was rein um direkt!! zu überschreiben?!
    Weiterhin in Zeilen 35-36 setzt du einfach die Zeiger weiter in Abhängigkeit von der Dateilänge. Nur warum bist Du Dir sicher, dass es passen wird?
    Weiterhin Du öffnest ständig die Dateien ohne sie zu schließen. Mein Wissensstand ist, das nur der Destruktor die Ressourcen von fstream freigibt. Die Open()-Methode tut es nicht.

    Aber so richtig lesbar ist dein Code nicht. Sorry 😞 🙂



  • Gast351353546346346 schrieb:

    Aber wie crypte ich denn direkt nen int Wert?

    da gibt es viele möglichkeiten. hier http://www.online-tutorials.net/xor/xor-verschlsseln-und-die-keylnge-bestimmen-kryptanalse-teil-1/tutorials-t-114-277.html zum beispiel machen sie es mit ner xor-verknüpfung, aber es gibt auch noch tausend andere möglichkeiten.


Anmelden zum Antworten