|
|
Title: C++ Debug Library
Author: Steve Kiraly (SteveKi) 6-17-1998 1-31-1999 3-03-1999
Purpose: The purpose of this document is to describe the design and document features of this debug library. It will in addition outline some of the basic design premises and include direction on how to extend or add features to this library.
Description: Everyone has at one time or another developed there own mini debug messging class, function or library which usually includes a set of macros that expand to calls to output strings to the debugger or console in the checked builds and nothing in the free builds. This debug library offers a similar feature however grows on this idea to permit sending the output string to one or many debug devices simultaniously.
Extensions: All file names have a dbg prefix because I wanted to ensure that it's obvious these files are debug files and can be ignored in the free version. If any files are added please stick to the dbg prefix for new file names. Do not add dependencies to dlls in this library that you would not normally have clients of this library link to. For example the back tracing code uses imagehlp.dll it does not implicity link to imagehlp.dll because this would require the client to link to imagehlp.dll. Sources files do not have an easy way to conditionally link to certain libraries in either the checked of free version. As a result clients are then equired to link to imagehlp.dll in both the checked and free version. If there is a library that you only need in this library and is not used in the checked version then lazy load the library, using LoadLibrary().
To Do List: 1. Add memory leak detection code, both C and C++ allocations.
2. Add memory debug output device type that is compatible with splx debug extension.
3. Add counter to critical section, that will be used to determine if we are in the critical when the TUnLock class is used.
4. Add global variable that can be set to indicate that the backtrace code should reload symbols using a new symbol path specified in the registry.
5. Add code for random failed allocations. Requirements include introducing random program memory allocations using backtraces to preventing duplicate allocation failures.
6. Implement the Debug serial terminal. This debug device will allow you to send output to a remote via a dumb serial terminal.
7. Create a method to track generic resources for leak detection. The current thinking is to create a set of macros for tracking and releasing a generic resource handle. The way this could work is the when a resouce is allocated it is entered into a mini database along with a backtrace. When the resource is release it is removed from the mini database. At the end of the program or in a stratigic checkpoint the resouces that are left in the mini database can be dump, these are potential resource leaks.
8. Look at the environment for the symbol path when capturing backtraces.
Example Usage:
-------------------------------------------------------------------------------
1. Display basic debug messages to the default device, debugger.
// // Initialize the debug library, this is optional. // DBG_INIT();
// // Open the debug message class, this function does the following. // // 1. Seting the module prefix to "DEBUG". // 2. The default output device will be enabled, i.e. Debugger. // 3. Trace, warning and error messages will be displayed. // 4. Error messages will break to the debugger. // DBG_OPEN(_T("DEBUG"), DBG_DEFAULT, DBG_TRACE|DBG_WARN|DBG_ERROR, DBG_ERROR);
// // Call to display a unicode debug message string. // DBG_MSG(DBG_TRACE, (_T("Trace testing Param %d String %s\n"), 1, _T("Test")));
// // Call to display a ansi debug message string. // DBG_MSG(DBG_TRACE, ("Trace testing Param %d String %s\n", 1, "Test"));
// // Close the debug message class, this is optional if you use DBG_RELEASE(). // DBG_CLOSE();
// // Release the debug library. // DBG_RELEASE();
-------------------------------------------------------------------------------
2. Dumping trace messages the debugger.
// // Initialize the debug library, this is optional. // DBG_INIT();
// // Open the message class. // DBG_OPEN(_T("TRACE"), DBG_DEFAULT, DBG_TRACE, DBG_NONE);
// // Display a entry and exit trace message after each scope. // // DBG_TRACE(_T("Test Scope 1")) { DBG_TRACE(_T("Test Scope 2")) }
// // Release the debug library. // DBG_RELEASE();
-------------------------------------------------------------------------------
3. Log messages to multiple devices, file, debugger.
// // Initialize the debug library, this is optional. // DBG_INIT();
// // Open the message class. // DBG_OPEN(_T("DEBUG"), DBG_DEBUGGER, DBG_TRACE, DBG_NONE);
// // Declare the debug file device handle. // DBG_HANDLE_(hDebugFile);
// // Attach the messages to file output device. // DBG_ATTACH_(hDebugFile, DBG_FILE, _T("output.log"));
// // Display a message, this message will be sent to both the debugger and the // output.log file. // DBG_MSG(DBG_TRACE, (_T( "Trace testing Param %d String %s\n"), 1, _T("Test")));
// // Detach the file device from the output stream, this step is optional if you // use either the DBG_CLOSE or the DBG_RELEASE functions they will release the // the attached devices. // DBG_DETACH_(hDebugFile);
// // Close the debug message class, this is optional if you use DBG_RELEASE(). // DBG_CLOSE();
// // Release the debug library. // DBG_RELEASE();
-------------------------------------------------------------------------------
4. Display message with time stamp and thread id.
// // Initialize the debug library, this is optional. // DBG_INIT();
// // Open the message class, displaying a thread id and time stamp. // DBG_OPEN(_T("DEBUG"), DBG_TRHEADID|DBG_TIMESTAMP|DBG_DEBUGGER, DBG_TRACE, DBG_NONE);
// // Display trace message. // DBG_MSG(DBG_TRACE, (_T("Trace testing Param %d String %s\n"), 1, _T("Test")));
// // Close the debug message class, this is optional if you use DBG_RELEASE(). // DBG_CLOSE();
// // Release the debug library. // DBG_RELEASE();
-------------------------------------------------------------------------------
5. Display message with custom time stamp and thread id formats.
DBG_OPEN(_T("DBG_TIME"), DBG_DEFAULT, DBG_TRACE|DBG_TIMESTAMP|DBG_THREADID, DBG_NONE);
DBG_SET_FIELD_FORMAT(DBG_TIMESTAMP, _T(" Tick Count (%x)"));
DBG_SET_FIELD_FORMAT(DBG_THREADID, _T(" Thread Id = [%d]"));
DBG_MSG(DBG_TRACE, ("Test Message\n"));
DBG_CLOSE();
-------------------------------------------------------------------------------
6. Capture macros used for capturing stack backtraces.
The symbol path by default will look in .;%_NT_SYMBOL_PATH%;_ALT_SYMBOL_PATH; if you need to specify an alternate symbol path the debug library will look in the following registry key for an alternate symbol path.
HKLM\Software\Microsoft\Windows NT\CurrentVersion\PrintSysDebugLibrary Sympath REG_SZ ="Your own symbol path"
// // Initialize the debug library, this is optional. // DBG_INIT();
DBG_CAPTURE_HANDLE(Capture); DBG_CAPTURE_OPEN(Capture, _T("nosymbols"), DBG_DEBUGGER, NULL); DBG_CAPTURE(Capture, 0, ("Ansi %d Multi Thread Test.\n", dwThread)); DBG_CAPTURE_CLOSE(Capture);
// // Capture stack back traces with symbols and output to debugger. // DBG_CAPTURE_HANDLE(Capture); DBG_CAPTURE_OPEN(Capture, _T("symbols"), DBG_DEBUGGER, NULL); DBG_CAPTURE(Capture, 0, (_T("Unicode %d Multi Thread Test.\n"), dwThread)); DBG_CAPTURE_CLOSE(Capture);
// // Capture stack back traces with symbols and output to file "backtrace.log" // DBG_CAPTURE_HANDLE(Capture); DBG_CAPTURE_OPEN(Capture, _T("symbols"), DBG_FILE, _T("backtrace.log")); DBG_CAPTURE(Capture, 0, (_T("Unicode %d Multi Thread Test.\n"), dwThread)); DBG_CAPTURE_CLOSE(Capture);
// // Release the debug library. // DBG_RELEASE();
-------------------------------------------------------------------------------
7. Misc assert and macro usage examples.
// // Some other useful macros. // // Call to output a string to the debugger with no formatting. // The passed string must use the _T() or TEXT() macros and // have a trailing semicolan; // DBG_RAW(_T("Trace message"));
// // Break to the debugger. // DBG_BREAK();
// // Normal assert message // DBG_ASSERT(FALSE);
// // Assert message with ansi description string // DBG_ASSERT_MSG(i==0, ("Null pointer found %s.\n", "Here"));
// // Assert message with unicode description string // DBG_ASSERT_MSG(i==0, (_T("Null pointer found %s.\n"), _T("Here")));
|