Debugging is a never-ending process. Although it's often thought of as a process to find and eliminate bugs in your programs, that's only half of the story. Debugging is also a programming tool. This type of debugging might better be thought of as diagnostics, which tell you what your program is doing at any given moment. While breakpoints will tell you much of what you need to know, other diagnostic methods are also available. In this article, we'll discuss one such tool: diagnostic macros. We'll show you what they are and how to use them in your programs.
TRACE("In my OnCreate handler...");
The text within quotes is sent to the diagnostic log file.
Both TRACE and WARN let you use the iostream streaming operators within the
macro. For example, to output the value of a particular variable to the
diagnostic log file, you could write code like the following:TRACE("Entering OnFormCreate handler...");
TRACE("ParamCount = " << ParamCount());
TRACE("ParamStr(0) = " << ParamStr(0));
In this case, the value of the ParamCount() function is output followed by the
value of ParamCount(0). (The ParamCount() function returns the number of
command-line parameters, and ParamStr() returns an individual command line
parameter. ParamStr(0) always returns the path and filename of the executable.)
The previous code snippet would result in the following entry to the diagnostic
log file:Trace Unit1.cpp 20: [Def] Entering OnFormCreate handler... Trace Unit1.cpp 21: [Def] ParamCount = 0 Trace Unit1.cpp 22: [Def] ParamStr(0) = E:\Project1.exeWe split some of the lines here--the text would all appear on a single line in the log file. We'll talk in just a minute about the format of the log file and how to use it. The WARN macro works like the TRACE, but WARN macro lets you test for a condition as well as send a text string to the log file. If the condition is met, the text is sent to the diagnostic log file; if the condition isn't met, then the text isn't sent. Here's an example:
WARN(Handle == 0, "Something went wrong...");The value of Handle is checked for a non-zero value. If Handle is 0, then the message is sent to the log file; if Handle contains a valid value, then nothing is written to the log file. WARN allows you to output only the messages that you want to see for a given condition. This helps to eliminate clutter in the log file so you can easily find the information you're looking for.
Figure A: When a message is generated, the OUTDBG1.TXT file appears in the Code
Editor.
Second, OUTDBG1.TXT isn't saved as part of your project when you use the Save or Save All command. It's treated as a temporary file, and its contents are discarded when you close the file or the project. In addition, you'll never be prompted to save OUTDBG1.TXT. You can explicitly save the log file with File | Save, if you wish.
| Note: DLL messages |
|---|
| You may have encountered OUTDBG1.TXT from time to time as you've worked with C++Builder. Once in a while, you'll see a message that warns of a DLL collision. This message is just for informational purposes. The warning simply tells you that the DLL couldn't be loaded at the requested memory location and therefore was loaded in another place in memory. You can happily ignore such messages. |
The messages sent to OUTDBG1.TXT are appended to any text already in the file. In other words, if you run your program repeatedly, the contents of OUTDBG1.TXT will grow--old message aren't removed, and new TRACE and WARN messages are added to the end of the file.
| Include the CHECKS.H header. | |
| Define __TRACE and __WARN in your application. |
Begin by including CHECKS.H in any units that use the TRACE and WARN macros, as follows:
#include <checks.h>If you forget to include this file, you'll get a compiler error about TRACE or WARN being undefined symbols. Next, define the __TRACE and __WARN symbols. If you fail to define these symbols, the TRACE and WARN macros won't work. You won't see any indication that the macros aren't working--you simply won't get any output in OUTDBG1.TXT.
You can define these symbols two ways. First, you can define them in one of your source code units or headers:
#define __TRACE #define __WARNNote that each symbol has two underscores preceeding the symbol name. An arguably better way to define the __TRACE and __WARN symbols is to add them to the Conditional Defines field in the Project Options dialog box. To do this, open the Project Options dialog box, then move to the Directories/ Conditionals page. Enter the following text in the Conditional Defines field:
__TRACE;__WARNAgain, be sure you put a double underscore before each symbol. Notice that a semicolon separates the symbols and that there are no spaces between them. Once you've performed these steps, you can begin to put the TRACE and WARN macros to work. Listing A contains a short program that illustrates how to use these C++Builder macros. The program consists of a form with an edit control and a button.
Listing A: DIAGSU.CPP
#define __TRACE #define __WARN //---------------------------- -----------------
#include <vcl\vcl.h>
#include <checks.h>
#pragma hdrstop
#include "DiagsU.h"
//----------------------------
-----------------
#pragma resource "*.dfm"
TForm1 *Form1;
//----------------------------
-----------------__fastcall
TForm1::TForm1
(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------
-------------------
void __fastcall TForm1::
FormCreate(TObject *Sender)
{
TRACE("Entering OnForm
Create handler...");
TRACE("ParamCount = "
<< ParamCount());
TRACE("ParamStr(0) = "
<< ParamStr(0));
}
//--------------------------
-------------------void __fastcall TForm1::
Button1Click
(TObject *Sender)
{
TRACE("In OnClick handler
for " <<
dynamic_cast<TComponent*
>(Sender)->Name
<< "...");
static int count;
count++;
// Output message if button has been
// clicked more than 5 times.
WARN(count > 5, "Button has
been clicked "
<< count << " times.")
TRACE("Edit1 contains: " <<
Edit1->Text.c_str());
}
//----------------------------
-----------------void __fastcall
TForm1::FormClose(TObject
*Sender, TCloseAction
&Action)
{
TRACE("Entering OnFormClose handler...");
TRACE("Application closing...");
}