Microsoft Visual Studio C Runtime Library has detected a fatal error



  • Ich bekomme immer folgenden Fehler
    "Microsoft Visual Studio C Runtime Library has detected a fatal error"
    sobald "insertMultiple" fertig ist.

    Die Ausgabe von "writeBufferToFile" ist genau was es sein soll.

    Woher kommt also dieser Fehler?

    void TMyBlockCache::insertMultiple(const myBlockLba lba, unsigned char* buffer, const unsigned int itemCount, const size_t itemLen)
    {
    	size_t         l = (itemLen > 0) ? itemLen : FItemSize;
    
    	for (unsigned int i = 0; i < itemCount; ++i) {
    		writeBufferToFile(buffer + (i * l), l, "B:\\cdrPirate_TestFiles\\__debug_buffer.tmp." + IntToStr(i));
    		insert(lba + i, buffer + (i * l), l);
    	}
    } // <<<
    
    // check cache
    		if (FBufferCache) {
    			if (FBufferCache->isCached(discLba)) {
    
    				// get pointer to cache
    				FBufferPointer = FBufferCache->getBuffer();
    
    			} else {
    
    				// seek track
    				int            rc     = FCdTracks[trackIdx]->seek(lba, usePregap);
    				int            bytes  = FCdTracks[trackIdx]->getTrackInfo().TrackInfo.BytesPerSector;
    				unsigned char* buffer = FCdTracks[trackIdx]->getBuffer();
    
    				writeBufferToFile(buffer, FCdTracks[trackIdx]->getBufferFrames() * bytes, "B:\\cdrPirate_TestFiles\\__debug_buffer.tmp");
    
    				// add to cache
    				if (rc == 1 /* seekUnbuffered ? */) {
    					// put all sectors in our block cache, maybe we need them later
    					FBufferCache->insertMultiple(discLba, buffer, FCdTracks[trackIdx]->getBufferFrames(), bytes); // <<<
    
    				} else {
    					// this should never happen as we already have this sector in our cache
    					cout << "TMyDiscFileInterface::seekTrack, FCdTracks[trackIdx]->seek(lba, usePregap) did not return 1, this should never happen." << endl;
    					FBufferPointer = FBufferCache->insert(discLba, buffer, bytes);
    				}
    
    			}
    
    		} else {
    
    			// cache is disabled
    			FCdTracks[trackIdx]->seek(lba, usePregap);
    			FBufferPointer = FCdTracks[trackIdx]->getBuffer();
    
    		}
    

    Call stack

    >	cdrPirateImageTool.exe!_crt_debugger_hook(int _Reserved)  Line 65	C
     	cdrPirateImageTool.exe!_call_reportfault(int nDbgHookCode, unsigned long dwExceptionCode, unsigned long dwExceptionFlags)  Line 167 + 0x6 bytes	C++
     	cdrPirateImageTool.exe!_invoke_watson(const wchar_t * pszExpression, const wchar_t * pszFunction, const wchar_t * pszFile, unsigned int nLine, unsigned int pReserved)  Line 155 + 0xf bytes	C++
     	cdrPirateImageTool.exe!_invalid_parameter(const wchar_t * pszExpression, const wchar_t * pszFunction, const wchar_t * pszFile, unsigned int nLine, unsigned int pReserved)  Line 110 + 0x14 bytes	C++
     	cdrPirateImageTool.exe!_invalid_parameter_noinfo()  Line 121 + 0xc bytes	C++
     	cdrPirateImageTool.exe!_fwrite_nolock(const void * buffer, unsigned int size, unsigned int num, _iobuf * stream)  Line 111	C
     	cdrPirateImageTool.exe!fwrite(const void * buffer, unsigned int size, unsigned int count, _iobuf * stream)  Line 83 + 0x11 bytes	C
     	cdrPirateImageTool.exe!TMyFileAccess::Write(void * _SrcBuf, unsigned int _ElementSize, unsigned int _Count)  Line 135 + 0x17 bytes	C++
     	cdrPirateImageTool.exe!TMyDiscFileWriterCueBin::writeBin(TMyDiscFileInterface & disc, std::basic_string<char,std::char_traits<char>,std::allocator<char> > outFilename, const bool seperateTrackFiles)  Line 185	C++
     	cdrPirateImageTool.exe!TMyDiscFileWriterCueBin::writeImage(TMyDiscFileInterface & disc, std::basic_string<char,std::char_traits<char>,std::allocator<char> > outFilename, const bool seperateTrackFiles)  Line 234 + 0x5f bytes	C++
     	cdrPirateImageTool.exe!main(int argc, char * * argv)  Line 130	C++
     	cdrPirateImageTool.exe!__tmainCRTStartup()  Line 278 + 0x12 bytes	C
     	kernel32.dll!7c817077() 	
     	[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]	
     	cdrPirateImageTool.exe!TMyDiscFileWriterCueBin::writeCue(TMyDiscFileInterface & disc, std::basic_string<char,std::char_traits<char>,std::allocator<char> > outFilename, const bool seperateTrackFiles)  Line 100 + 0xf9 bytes	C++
    


  • OK, das ist ein Problem von "nicht gut genug mit dem Debugger auskennen".
    Hier ist was du machst:
    * Programm im Debugger starten, warten bis die Fehlermeldung kommt
    * Im Assertion-Dialog auf "Wiederholen" ("Retry") drücken
    * Doppelklick auf die cdrPirateImageTool.exe!_fwrite_nolock(...) Zeile im Callstack
    * Nachgucken welcher Parameter ungültig ist
    * Doppelklick auf die cdrPirateImageTool.exe!TMyFileAccess::Write(...) Zeile im Callstack
    * Nachgucken wie es dazu kommt dass du nen ungültigen Parameter übergibst
    * STOP drücken um das Programm abzubrechen
    * Problem fixen
    * Neu compilieren, nochmal probieren

    p.S.: nach einem Doppelklick auf eine Zeile im Callstack steht der Cursor oft eine Zeile zu weit unten, also unmittelbar *nach* dem Aufruf "in" dem sich das Programm gerade befindet. Ist anfangs verwirrend, aber man gewöhnt sich halbwegs schnell daran.



  • Super jetzt geht es, ich hatte vergessen "FBufferPointer" zu setzten war noch auf NULL.



  • Siehste, debuggen ist ganz easy 🙂



  • hustbaer schrieb:

    * Doppelklick auf die cdrPirateImageTool.exe!_fwrite_nolock(...) Zeile im Callstack
    * Nachgucken welcher Parameter ungültig ist
    * Doppelklick auf die cdrPirateImageTool.exe!TMyFileAccess::Write(...) Zeile im Callstack
    * Nachgucken wie es dazu kommt dass du nen ungültigen Parameter übergibst

    Warum gerade diese beiden Zeilen im Callstack? Wie kommst Du darauf?



  • Naja... wo sonst?
    Fangen wir ganz "oben" an (oben in der von a2875243 geposteten Form).

    Da haben wir Funktionen mit folgenden Namen:

    _crt_debugger_hook               <---- hier wurde das Programm unterbrochen
    _call_reportfault
    _invoke_watson
    _invalid_parameter
    _invalid_parameter_noinfo
    _fwrite_nolock
    fwrite
    TMyFileAccess::Write
    ...
    ...
    
    ...
    main                             <----- hier wurde das Programm gestartet
    

    Bis inklusive _invalid_parameter_noinfo sind das ganz eindeutig Funktionen die für Fehlerbehandlung zuständig sind. D.h. da wurde der Fehler schon erkannt, d.h. wir sind zu weit "oben".
    Dann kommt _fwrite_nolock und dann die offizielle CRT Funktion fwrite .
    Es ist also anzunehmen dass die "if (ungültig)" Abfrage in _fwrite_nolock steht. Schliesslich ist _fwrite_nolock die Funktion die den Error-Handler ( _invalid_parameter_noinfo ) Aufruft.
    fwrite ist uninteressant, da wird vermutlich bloss ne Mutex gelockt und dann an _fwrite_nolock weitergeleitet - zumindest impliziert das Namenspaar "xxx" und "xxx_nolock" genau das.

    OK, nun wissen wir welcher Parameter ungültig war, aber noch nicht wieso - der Fehler wird ja vermutlich nicht in der CRT selbst sein, sondern im eigenen Code. Also gucken wir weiter nach "unten" zur ersten eigenen Funktion. Und TMyFileAccess::Write klingt sehr verdächtig nach eigenem Code. Vorausgesetzt diese Annahme stimmt, dann ist das die erste Stelle mit eigenem Code, und daher die Stelle wo man üblicherweise anfängt zu suchen (also ich zumindest).

    Wenn TMyFileAccess::Write auch bloss weiterleitet, und schon selbst nen ungültigen Parameter bekommen hat, dann halt weiter zur nächsten Funktion und zur nächsten - so lange bis wir die Stelle gefunden haben wo es anfängt schief zu laufen.

    In normalen, "synchronen" Programmen findet man die meisten Fehler so ziemlich schnell.


Anmelden zum Antworten