Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

First Step to Make a Simple Debugger Class

1.44/5 (5 votes)
24 Jun 2010CPOL2 min read 1   110  
This class gives you an idea to make your own debugging class.

Introduction

Usually about 80% of a programmer's time is spent debugging code. This shows how important debugging is. In general, MSVC++ provides a great debugger as well as debugging APIs, but it has several limitations. For example, you cannot have a debug print function like printf.

Background

As an aid to assist in debugging, any developer can make his/her own debugging class with functions that do whatever they want. As a preliminary step towards that goal, I developed the DBG class with two functions useful for debugging:

  • DbgPrint() which works like printf() for printing, and
  • GetLinkageLog() which logs all memory linkages to the Debug window.

Both functions use the MSVC++ Debugging APIs. You can modify these or define your own functions by starting with the code presented here.

Using the Code

The debug.zip file can be downloaded from the above link and contains two files: debug.h and debug.cpp. To use them, just add both files to your project's header and source directory and add the #include "debug.h" directive to stdafx.h for your project.

In debug.h, I have already added the necessary defines and includes to enable debugging. The DBG class is declared as follows:

C++
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define  PRINT_SIZE 100
class DBG
{ char* strPrint;
 int ptr;
 public:
  DBG()
  {
   strPrint = new char [ PRINT_SIZE ];
   ptr = 0;
  }
  ~DBG()
  {
   delete strPrint;
  }
  void GetLinkageLog( );
  void DbgPrint( char *str , ... );
};

To use the DBG class, you simply create an object of this class and use its functions. Simple code snippets illustrating the use of the DBG class are given below:

C++
#define SERVER_PORT 12345
#define BUF_SIZE 100  // block transfer size  
#define QUEUE_SIZE 10 
int _tmain(int argc, _TCHAR* argv[])
{
 
 int  b, l, on = 1;
 char recvbuf<buf_size> = { }; 
 SOCKET s, sa;
 struct sockaddr_in channel;  // holds IP address 
 WORD wVersionRequested;
 WSADATA wsaData;
 int  err;
 int  bytesRecv;
 DBG obj;
 obj.DbgPrint( "MAIN : %d ", 1 );
 
 //--- INITIALIZATION -----------------------------------
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  printf("WSAStartup error %ld", WSAGetLastError() );
  WSACleanup();
  return false;
 }
 //------------------------------------------------------
 char* a = new char [ 50 ] ;
 obj.GetLinkageLog( );</buf_size>

Please note that my DbgPrint() supports only the %d, %c, %s and %f format specifiers because I only defined those in the union and switch statements of the DbgPrint() function as shown below. Of course, you can easily add additional format specifiers or remove any that are not required.

C++
#include "stdafx.h"
void DBG::DbgPrint( char* str, ... )
{
   va_list vl;
   int i;
   char* temp = this->strPrint;
 
   //  str is the last argument specified; all
   //   others must be accessed using the variable-
   //   argument macros.
   va_start( vl, str );
   // Step through the list.
   for( i = 0; str[i] != '\0'; ++i ) {
      union Printable_t {
         int     d;
         float   f;
         char    c;
         char   *s;
      } Printable;
      switch( str[i] ) {   // Type to expect.
   case '%' :
    switch( str[++i] ) {
     case 'd':
     Printable.d = va_arg( vl, int );
     this->ptr = sprintf ( temp, "%d", Printable.d );
     temp = temp + this->ptr ;
     break;
     case 'f':
      Printable.f = va_arg( vl, double );
      this->ptr = sprintf ( temp, "%f", Printable.f );
      temp = temp + this->ptr ;
     break;
     case 'c':
      Printable.c = va_arg( vl, char );
       this->ptr = sprintf ( temp, "%c", Printable.c );
       temp = temp + this->ptr ;
     break;
     case 's':
      Printable.s = va_arg( vl, char * );
      this->ptr = sprintf ( temp, "%s", Printable.s );
      temp = temp + this->ptr ;
     break;
     default:
      break;
    }
    break;
         default:
    this->ptr = sprintf ( temp, "%c", str[i] ); 
    temp = temp + this->ptr ;
         break;
      }
   }
   OutputDebugString( this->strPrint );
   va_end( vl );
}

Points of Interest

Using the code presented here as a starting point, anyone who is interested can make their own debugging class.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)