Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

302 lines
9.0 KiB

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")));