Speicherproblem



  • Hallo,
    ich bin gerade dabei Spiele Programmierung mit C++ und DirectX 9 zu lernen. Nun wollte ich eine Log Funktion einbauen, die auch bedingt lange funktioniert. Sie wird vllt. 5-6 mal aufgerufen und danach sagt mir der Compiler:

    Windows hat einen Haltepunkt in cGame.exe ausgelöst.
    
    Dies kann auf eine Beschädigung des Heaps zurückzuführen sein, die auf ein Problem in cGame.exe oder in einer der geladenen DLLs hinweist.
    
    Dies kann auch darauf zurückzuführen sein, dass der Benutzer F12 drückt, während cGame.exe den Fokus hat.
    
    Weitere Analyseinformationen finden Sie möglicherweise im Ausgabefenster.
    

    in der Datei new.cpp in der Zeile 59 deren Code

    while ((p = malloc(size)) == 0)
    

    ist. Ich konnte das Problem auf die Funktion die in den Log schreibt zurückführen und noch genauer auf die Funktion die bei mit einen Zeit String erstellt.

    Die Funktion eWriteLog, die in die Log Datei schreibt:

    eResult eWriteLog (char *sLogEntry, eLogType logType)
    {
    	if (logFile)
    	{
    		char *sTimePrefix = "[";
    		char *sTime = eGetDiffTime();
    		char *sTimePostfix = "] ";
    
    		char *postfix = "<br/>";
    		char *prefix;
    		if (logType == LT_ERROR)
    			prefix = "<font color=\"red\">Fehler: </font>";
    		else
    			prefix = "<font color=\"blue\">Information: </font>";
    
    		fwrite(sTimePrefix, strlen(sTimePrefix) * sizeof(sTimePrefix[0]), 1, logFile);
    		fwrite(sTime, strlen(sTime) * sizeof(sTime[0]), 1, logFile);
    		fwrite(sTimePostfix, strlen(sTimePostfix) * sizeof(sTimePostfix[0]), 1, logFile);
    
    		fwrite(prefix, strlen(prefix) * sizeof(prefix[0]), 1, logFile);
    
    		fwrite(sLogEntry, strlen(sLogEntry) * sizeof(sLogEntry[0]), 1, logFile);
    		fwrite(postfix, strlen(postfix) * sizeof(postfix[0]), 1, logFile);
    
    		return E_OK;
    	}
    	else
    	{
    		return E_FAILED;
    	}
    }
    

    und die Funktion eGetDiffTime, die den Zeit String erstellt:

    char* eGetDiffTime()
    {
    	time_t cCurrentTime = time(NULL);
    
    	double dDiffTime = difftime(cCurrentTime, *cStartTime);
    
    	double dHours = dDiffTime / 60 / 60;
    	double dMinutes = dDiffTime / 60;
    	double dSeconds = dDiffTime;
    
    	int iHours = dHours;
    	int iMinutes = dMinutes - (iHours * 60 * 60);
    	int iSeconds = dSeconds - (iMinutes * 60) - (iHours * 60 * 60);
    
    	char *sHours = new char;
    	char *sMinutes = new char;
    	char *sSeconds = new char;
    
    	if (iMinutes < 10)
    		sprintf(sMinutes, "0%d", iMinutes);
    	else
    		sprintf(sMinutes, "%d", iMinutes);
    	if (iSeconds < 10)
    		sprintf(sSeconds, "0%d", iSeconds);
    	else
    		sprintf(sSeconds, "%d", iSeconds);
    	if (iHours < 10)
    		sprintf(sHours, "0%d", iHours);
    	else
    		sprintf(sHours, "%d", iHours);
    
    	char *sTime = new char;
    	sprintf(sTime, "%s:%s:%s", sHours, sMinutes, sSeconds);
    
    	return sTime;
    }
    

    cStartTime ist global als time_t deklariert:

    time_t *cStartTime;
    

    und wird am anfang geladen:
    [cpp]
    cStartTime = (time_t*)malloc(sizeof(time_t));
    time(cStartTime);
    [/c]

    Mir ist klar das das nicht sehr elegante Lösungen sind, aber ich bin noch nicht so erfahren in C++, für Verbesserungen währe ich dankbar.
    Ich hoffe ihr könnt mir bei dem Problem helfen.

    Progglord



  • Progglord schrieb:

    Ich bin gerade dabei Spiele Programmierung mit C++ und DirectX 9 zu lernen...

    cStartTime = (time_t*)malloc(sizeof(time_t));
    

    Äh, welches Buch ist das? Den Returnwert von malloc zu casten ist "C++-typisch" 🤡



  • Böser C Code, hat mMn nix mit C++ zu tun.

    char *sHours = new char;
    

    Der Pointer wird direkt im Anschluss in sprintf benutzt. Buffer Overflow, anyone?

    mfg, René~



  • Ich habe jetzt nach weiteren Stunden experimentieren und suchen rausgefunden das es am String liegt der übergeben wird.

    char *errorString = new char;
    		sprintf(errorString, "Das D3DDevice konnte nicht erstellt werden (%s): %s", DXGetErrorString(hResult), DXGetErrorDescription(hResult));
    
    		eWriteLog("Das D3DDevice konnte nicht erstellt werden", LT_ERROR);
    		return E_FAILED;
    

    Es liegt hier an DXGetErrorString(hResult) und/oder DXGetErrorDescription(hResult). Ich forsche noch ein wenig und evtl. könnt ihr mir ja auch helfen das Problem zu lösen.

    @Vicious Falcon: Das ist aus keinem Buch :D, ich arbeite nur irgendwie gerne mit malloc :D.



  • Progglord schrieb:

    char *errorString = new char;
    

    Alter, wenn du schon C programmieren willst, dann lern es gefälligst richtig damit du dir nicht tausende von Buffer Overflows in deinen Code haust...

    mfg, René~



  • Ich seh schon die beiden DXGetError Funktionen geben WCHAR* zurück.
    Wie kann ich das denn richtig in char* umwandeln ?

    @NewSoftzzz: Wenn du schon rummeckerst, dann sag mir wenigstens wie es richtig geht.

    EDIT:
    Noch eine Frage:
    Wie kann ich denn einen Buffer Overflow vorbeugen, bzw. wann wird dieser ausgelöst?



  • C++ bietet eine Klasse fuer Zeichenketten an, std::string. Auch solltest du dich mehr mit den Grundlagen vertraut machen und vorher ein reines C++ Buch lesen, bevor du Spiele damit machen kannst.



  • std::string kenn ich auch, es ist bloß ein wenig her :D. Danke ich werde es mal so machen.



  • wieso du nur so ne doofe antwort bekommen hast, liegt daran, dass keiner weiß, ob du nun C oder C++ programmierst...
    der C weg wäre malloc, C++ std::string oder zumindest new char[SIZE].

    bb



  • Oder man legt einfach ein Array an.



  • feigling schrieb:

    Oder man legt einfach ein Array an.

    Rohe Arrays sind mühsam und fehleranfällig. Die würde ich wirklich nur verwenden, wenn es gar keine sinnvollen Alternativen wie std::tr1::array gibt und man keinesfalls die Möglichkeit hat, eine Viertelstunde zur Implementierung einer solchen aufzuwenden.



  • Ich hatte vergessen "unter C" dazuzuschreiben 😃



  • Progglord schrieb:

    Ich seh schon die beiden DXGetError Funktionen geben WCHAR* zurück.
    Wie kann ich das denn richtig in char* umwandeln ?

    Da du unter Windows arbeitest, schau dir mal die Funktion WideCharToMultiByte (das Pendant ist, wer hätte es gedacht, MultiByteToWideChar) an.

    const WCHAR* wstr = L"wstring";
    size_t len = wcslen(wstr);
    std::vector<char> v(len+1,0);
    WideCharToMultiByte(CP_ACP,0,wstr,len,&v[0],len,0,0);
    // mit &v[0] arbeiten
    


  • feigling schrieb:

    Ich hatte vergessen "unter C" dazuzuschreiben 😃

    Ich denke, als C-Programmierer würde ich mir mit der Zeit sicher auch irgendwas überlegen... 😉


Anmelden zum Antworten