Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Useful Debugging Macros

0.00/5 (No votes)
14 Dec 1999 2  
A set of handy Debugging macro facilities without MFC
  • Download source files - 1.5 Kb
  • MFC comes with a set of several useful debugging macros. We've all used these macros numerous times and are quite familiar with them. How many times, however, have you been writing a piece of non-MFC code and wished you had the same macros available? Standard C/C++ come with only one macro that is at least similar to the MFC ASSERT macro, namely assert. However, this particular assertion macro is not as elegant as the MFC version which drops you directly into the code at the line of the assertion.

    Or maybe you have some debugging needs that go beyond those available by the MFC macros. Maybe you're trying desperately to track down a memory over run bug, for instance.

    Hopefully, this article will come to your rescue for these problems!

    The header file found in the download, <debug.h>, defines several macros useful for debugging code. Many of these macros will be familiar to MFC programmers, since they go by the same name and provide the same functionality. In fact, if MFC has been included before this header file then the MFC versions of these macros are used. Above and beyond the MFC macros, several other macros have been defined to provide functionality that Microsoft forgot. Below you'll find a general description of the macros present.

    ASSERT

    The ASSERT macro is identical the MFC macro of the same name. It's used to assert conditions within code during debug builds (when _DEBUG is defined). If the assertion fails then the program will break at the line the assertion was made.

    Example:

    ASSERT(a < 1);
    

    VERIFY

    The VERIFY macro is identical to the MFC macro of the same name. It's similar to ASSERT, but the condition is evaluated even for release builds, although a break will occur only in debug builds.

    Example:

    VERIFY(pWnd = GetDlgItem(IDC_MYEDIT));
    

    TRACE

    The TRACE macro is identical to the MFC macro of the same name. It's used to send text to the debug output window. It's syntax is similar to that of printf.

    Example:

    TRACE("Name: %s\n", obj.name());
    

    INFO

    The INFO macro is similar to the TRACE macro. Unlike TRACE, INFO prefixes the text with the file name and line number where the INFO was invoked, as well as appending a new line.

    Example:

    INFO("Name: %s\n", obj.name());
    

    DBG

    The DBG macro is used to invoke code for debug builds only.

    Example:

    DBG(AfxMessageBox("I'm here!"));
    

    BREAK

    The BREAK macro is used to force a program to break for debug builds. When the line where the BREAK is called is run, the program will halt and the debugger will go to that line.

    Example:

    BREAK();
    

    DECL_DOG_TAG and CHECK_DOG_TAG

    These macros are two of the most complex debugging macros found in this header. They are used to help detect memory corruption caused by memory over runs. I acquired this technique from a magazine article some time ago. Unfortunately, I can't recall where. If anyone knows please send me an e-mail so I can't give proper recognition to the original author.

    To use "dog tags" you first must declare them within a class definition using DECL_DOG_TAG. After this you can verify the integrity of memory by calling CHECK_DOG_TAG within your code. Typically you'll declare two dog tags within a class, one as the first class member and one as the last. It's also helpful to define a method to verify the integrety of the class by using these dog tags. Then client code can check the validity of the class by calling this method. See the example below for a demonstration of this.

    Example:

    class MyClass
    {
    private:
    	DECL_DOG_TAG(MyClassBegin);
    	
    	// All other class data should be declared here.  Removed for brevity.
    
    	
    private:
    	DECL_DOG_TAG(MyClassEnd);
    	
    #ifdef _DEBUG
    public:
    	void VerifyIntegrity() const	// Call this to check the dog tags
    
    		{ CHECK_DOG_TAG(MyClassBegin); CHECK_DOG_TAG(MyClassEnd); }
    #endif
    };
    
    // Later in the code:
    
    void func(MyClass& obj)
    {
    	DBG(obj.VerifyIntegrity());		// Check the object's integrity
    
    }
    

    Using the above code, if the object's integrity has been corrupted (typically by a memory over run in your code) then an ASSERT will fail on a call to VerifyIntegrity within the CHECK_DOG_TAG macro.

    I hope you find this header useful. If you know of any other debugging macros then drop me a line. I'll add them to later releases of this header.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here