//----------------------------------------------------------------------------- // NastDebug.cpp //----------------------------------------------------------------------------- #include "NastDebug.h" #include "NastDumpContextFile.h" #include #include #include // nur fuer Unix #ifndef _MSC_VER #include #endif //---------------------------------------------------------------------------- // Meldungen in den error DumpContext schreiben und das Programm verlassen //---------------------------------------------------------------------------- static CNastDebug NastDebug; CNastDumpContext* CNastDebug::m_pNastDumpErrors = new CNastDumpContextFile(cerr); CNastDumpContext* CNastDebug::m_pNastDumpWarnings = new CNastDumpContextFile(cerr); CNastDumpContext* CNastDebug::m_pNastDumpLogfile = new CNastDumpContextFile(cout); //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void CNastDebug::dumpContextErrors( CNastDumpContext *pDC ) { m_pNastDumpErrors = pDC; }; void CNastDebug::dumpContextWarnings( CNastDumpContext *pDC ) { m_pNastDumpWarnings = pDC; }; void CNastDebug::dumpContextLogfile ( CNastDumpContext *pDC ) { m_pNastDumpLogfile = pDC; }; CNastDumpContext& CNastDebug::dumpContextErrors() { return *m_pNastDumpErrors; } CNastDumpContext& CNastDebug::dumpContextWarnings() { return *m_pNastDumpWarnings; } CNastDumpContext& CNastDebug::dumpContextLogfile() { return *m_pNastDumpLogfile; } CNastDebug::CNastDebug() { // vorerst nichts zu tun } CNastDebug::~CNastDebug() { dumpContextErrors().flush(); dumpContextWarnings().flush(); dumpContextLogfile().flush(); delete CNastDebug::m_pNastDumpErrors; delete CNastDebug::m_pNastDumpWarnings; delete CNastDebug::m_pNastDumpLogfile; CNastDebug::m_pNastDumpErrors = NULL; CNastDebug::m_pNastDumpWarnings = NULL; CNastDebug::m_pNastDumpLogfile = NULL; } //---------------------------------------------------------------------------- // Meldungen in den error DumpContext schreiben und das Programm verlassen //---------------------------------------------------------------------------- void CNastDebug::fatalError(const char *szAssertion, const char *szFilename, int nLine, const char *szFunction, const char *szMessage) { CNastDumpContext &dumpContext = CNastDebug::dumpContextErrors(); dumpContext << NastConfigString(); dumpContext << "\n"; if( szAssertion ) // durch ein NAST_ASSERT... ausgeloest ? { dumpContext << "!!! NAST_ASSERT failed\n"; } if( szFilename ) // Filename angegeben ? dumpContext << szFilename << ":"; dumpContext << nLine << ":"; if( szFunction ) // Funktionsname angegeben ? dumpContext << szFunction << "\n"; if( szAssertion ) // Assertion als String angegeben ? { dumpContext << "\n"; dumpContext << "'" << szAssertion << "'"; } dumpContext << "\n\n"; if( szMessage ) // Message angeben ? dumpContext << szMessage << "\n"; dumpContext << "\n"; dumpContext.flush(); // und auf jedem Fall rausschreiben fatalExit(); // und nichts wie raus } void CNastDebug::fatalExit() { // abort erhaelt im Gegensatz zu exit den Stackframe // Wenn man das Programm mit einem Debugger laufen laesst, // dann kann man nach einem FatelExit() noch die lokalen Variablen // anschauen. // Bei gdb z.B. bt (Backtrace) // IDEE vielleicht laesst sich hier sogar noch ein automatischer // Start des Debuggers reinfummeln. Mit gdb muesst das // funktionieren. Man kann gdb an einen laufenden Prozess // anfuegen. // Wenn es die Funktion abort() aus irgendwelchen Gruenden // nicht geben sollte kann man stattdessen auch ein signal // SIGABORT an den Prozess selbst schicken. // falls die Envirnmentvariable NAST_DEBUGGER gesetzt ist // den Debugger starten // noch alles rausschreiben // so funktionierts leider nicht /* char *szProg = getenv("NAST_DEBUGGER"); if( szProg ) // NAST_DEBUGGER gesetzt ? { char buffName[100]=""; // lang genug fuer den Programmnamen char buffPID[100]=""; // lang genug fuer ProzessID sprintf("%s", "debug" ); sprintf("%d", getpid()); if( fork() == 0 ) // child ? { // Hmm, jetzt braeuchten wir den vollen Namen des Programm // mit Pfad. // char *const argv[] = { szProg, buffName, buffPID, 0}; execvp( szProg, argv ); } } */ abort(); }