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:
#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:
#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; WORD wVersionRequested;
WSADATA wsaData;
int err;
int bytesRecv;
DBG obj;
obj.DbgPrint( "MAIN : %d ", 1 );
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.
#include "stdafx.h"
void DBG::DbgPrint( char* str, ... )
{
va_list vl;
int i;
char* temp = this->strPrint;
va_start( vl, str );
for( i = 0; str[i] != '\0'; ++i ) {
union Printable_t {
int d;
float f;
char c;
char *s;
} Printable;
switch( str[i] ) { 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.