![]() |
Development Lifecycle »
Debug Tips »
General
Advanced
Debug ToolkitBy Keith WestleyA complete debug toolkit to add intelligent debugging capability to your application. |
VC6, Dev, QA
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
So you have written a great application and rolled it out to all your users and a week later you get the dreaded email:
Downloaded your program and I love it but it crashed. Can you please fix it.
You didn't expect details ... did you? So now you go through an extended exchange with the user trying to tie down the bug and eventually you give up and add it to the too hard basket in case someone else experiences the problem.
Of course you could ask the user to install Dr Watson or another tool which captures information when an application experiences an exception but what if the problem is a hang or if you would like internal application state information when the problem occured.
There is a better way. Using the debug toolkit outlined in this article you can get the users to send to you a file which provides:
The trace log not only contains statements you have traced out. When an error occurs such as an exception, a hang or an assert fails the following details are dumped to the trace log so you can get a picture of what was happening:
These are produced based on the following events:
To get all of this you actually need do very little coding and can easily enhance or limit the functionality without the need to modify directly the provided code.
One of the design goals here was to make this class very easy to incorporate into an existing or new application. The main class is CDebugToolkit. It also has some helper classes but you should never need to access them. CDebugToolkit has been designed to form the base class for your own debug toolkit class in which you will override numerous methods and occasionally call methods on the base class. If you find yourself changing CDebugToolkit then either you have found a bug (in which case let us know) or you are providing a generic enhancement which could be used by others (in which case also let us know). In all other circumstances I would hope the functionality could live in the derived class.
By sticking with this approach you should be able to easily incorportate enhancements if/when they are made.
BOOL AddFile(const CString& sFile, const BOOL fTestDLL = FALSE, const BOOL fTestFile = FALSE);Adds a file to the list of files that will be dumped should a log be required.
Returns FALSE if the file was to be tested and the test failed.
BOOL AddCOM(const CString& sFile, const CLSID clsid, const BOOL fTest = FALSE);Adds a COM objects to the list of COM objects that will be dumped should a log be required.
Returns FALSE if the COM object was to be tested and it failed.
virtual void Assert(DWORD dwLine, const CString& sFile, BOOL fCondition, const CString& sCondition, const CString& sDescription = "");Evaluates fCondition. If it is FALSE then it writes trace output with details of the line, the condition and an optional description. See the DT_ASSERT* macros for an easy way to use this function. This is a virtual function so you can always replace it in your derived class.
virtual void Trace(const CString& sOut, const DWORD dwFilterFlag = 0xFFFFFFFF, const BOOL fForce = FALSE);Writes out a message to the trace log. See the DT_TRACE* macros for an easy way to use this function. This is a virtual function so you can always replace it in your derived class.
OnTrace method. virtual BOOL DumpToFile(const CString& sFile, const CString& sPre = "");
virtual void DumpToFile(CFile& file, const CString& sPre = "");Writes all debug information to a log file. These are virtual functions so you can always replace them in your derived class.
Returns FALSE if the file could not be created.
void Delete(void);Deletes the cicular log file used to track trace output.
void Reset(void);Calling this function causes the debug toolkit to reload the debug options. Use this function if you want to turn on/off debug capabilities at runtime.
void SetTraceFilter(const DWORD dwFilter)This function sets the trace filter 32 bit flag which gets and'd with each trace request.
void SetSuspendHang(const BOOL fSuspend)This function suspends and re-activates the automated hang detection routine. Typically you would suspend this routine when performing particularly long tasks which do not allow the thread to process messages.
static CDebugToolkit* GetDebugToolkit(void)This function is a static function used to access the single instance of the debug toolkit. This function is used by the DT_ macros to allow you to easily write code to call instance methods.
CDebugToolkit(void);It is essential you call the base class constructor when constructing your derived class. You should also set any of the Debug Toolkit member variables that you don't like the default values for:
You would also typically add any files and COM objects that you want checking or dumping.
BOOL Initialise(void);This method should be called from your derived classes constructor just before it returns. It is critical that you have set all options prior to calling this function.
Returns FALSE if an error occured in initialisation.
DT_TRACE[0..3](s, p1, p2, p3)These macros are shortcuts for calling the Trace method. Using this macro prevents using filtering. This macro is used in an identical manner to MFCs TRACE[0..3] macros.
DT_TRACEF[0..3](f, s, p1, p2, p3)These macros are identical to DT_TRACE[0..3] except the additional f parameter allows you to pass a 32 bit flag field which will be and'd with the trace filter flag and only traced if at least 1 set bit matches.
DT_ASSERT(b)This macro is a shortcut for calling the Assert method. This macro is used in an identical manner to MFCs ASSERT macro.
DT_ASSERTS(b, s)This macro is a shortcut for calling the Assert method. It extends the DT_ASSERT macro in that it allows you to describe what you are asserting.
These methods have been specifically designed to be overridden in your class that derives from CDebugToolkit. Please do not change the methods directly.
virtual BOOL OnAssert(void);Called to see if you want the assert handled. If you want the assert handled return TRUE.
virtual void OnEndAssert(void);Called once the assert has been accepted and handled. Allows you to do some post assert processing such as maybe saving a log file and suggesting the user mail it to you.
virtual BOOL OnException(struct _EXCEPTION_POINTERS *pExceptionInfo);Called to see if you want to handle the exception. If you want the exception handled return TRUE.
virtual void OnEndException(void);Called once the exception has been accepted and handled. You need to be very careful what you do here as exceptions usually mean something is quite wrong.
virtual BOOL OnHang(void);Called to see if you want to handle the hang automatically detected. If you want the hang handled return TRUE. You may want to ask the user if the program appears to have hung ... just in case.
virtual void OnEndHang(void);Called once the hang has been accepted and handled. Allows you to do some final processing before the task is killed. BEWARE when this method is called you are not running in the main thread.
virtual BOOL OnUserHang(void);Called to see if you want to handle the user reported hang. If you want the hang handled return TRUE.
virtual void OnEndUserHang(void);Called once the user reported hang has been accepted and handled. Allows you to do some final processing before the task is killed. BEWARE when this method is called you are not running in the main thread.
virtual BOOL OnTrace(const DWORD dwFilterFlag);Called to see if you want the trace processed. If you want the trace handled return TRUE.
virtual void OnReset(void);Called to allow you to change debug toolkit processing options before debugging is restarted.
virtual BOOL OnDelete(void);Called to allow you to do some processing before the delete request is handled. Return FALSE to cancel the delete.
virtual void OnAbnormalExit(void);Called to allow you to do some processing when we detect the program did not exit normally last time it was run. This function is usually run prior to completion of the application constructor which limits some of the MFC functionality you can use.
virtual void OnTestDLLFail(const CString& sFile, DWORD dwError);Called when a DLL could not be loaded. Override this if you want to tell the user that a critical DLL is missing.
virtual void OnTestCOMFail(const CLSID clsid, const CString& sFile, DWORD dwError);Called when a COM file could not be loaded. Override this if you want to tell the user that a critical COM object is missing.
virtual void OnTestFileFail(const CString& sFile, DWORD dwError);Called when a file could not be found. Override this if you want to tell the user that a critical file is missing.
virtual CString GetDumpOtherAtEvent(void);Allows you to provide additional data to write to the trace log when a hang, exception or assert event occurs.
virtual CString GetDumpOtherAtSave(void);Allows you to provide additional data to write to the log file when it is being written to disk.
virtual void GetOptionDescriptions(CString& sOptionDescriptions);Allows you to dump in human readable form the options currently in effect.
virtual void ExportOptions(CFile& file);Allows you to dump in machine readable (but text) form to options currently in effect.
VERSION.LIB to your link options.
Generate mapfile option in your projects link options.
Assembly with Source Code.
CApplication derived class to add a new public member variableCMyDebugToolkit m_mdt;
#include "MyDebugToolkit.h" to the top of you CApplication derived class header file. You may need to do the same in other c++ files which will call the debug toolkit.
CMyDebugToolkit class.
ASSERT() and TRACE[0..3] calls with the DT_ equivaluent.
CAUTION: When running your code under the debugger this class will not trap exception events. This is because the debugger takes priority and traps it first.
There is obviously a lot of functionality here but there are also lots of possible enhancements. Should you make any or have any suggestions please let me know.
Here are some possible enhancements I have thought of but either don't have the time or equipment to do.
NOTE: I do post fixes to the code project site but sometimes it can take a few days for them to get there. The latest source is always available here.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 27 Mar 2000 Editor: Chris Maunder |
Copyright 2000 by Keith Westley Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |