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 diecdrPirateImageTool.exe!_fwrite_nolock(...)
Zeile im Callstack
* Nachgucken welcher Parameter ungültig ist
* Doppelklick auf diecdrPirateImageTool.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 probierenp.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 diecdrPirateImageTool.exe!TMyFileAccess::Write(...)
Zeile im Callstack
* Nachgucken wie es dazu kommt dass du nen ungültigen Parameter übergibstWarum 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 Funktionfwrite
.
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.