65.9K
CodeProject 正在变化。 阅读更多。
Home

创建简单调试器类的第一步

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.44/5 (5投票s)

2007年10月29日

CPOL

2分钟阅读

viewsIcon

23318

downloadIcon

127

这个类可以让你了解如何制作自己的调试类。

引言

通常,程序员大约 80% 的时间都花在调试代码上。这表明调试的重要性。通常,MSVC++ 提供了优秀的调试器以及调试 API,但它存在一些限制。例如,你无法拥有像 printf 这样的调试打印函数。

背景

为了辅助调试,任何开发者都可以创建自己的调试类,其中包含执行任何所需功能的函数。作为实现这一目标的第一步,我开发了 DBG 类,其中包含两个对调试有用的函数:

  • DbgPrint(),它像 printf() 一样用于打印,以及
  • GetLinkageLog(),它将所有内存链接记录到调试窗口。

这两个函数都使用了 MSVC++ 调试 API。你可以修改这些函数,或者从这里提供的代码开始定义你自己的函数。

Using the Code

debug.zip 文件可以从上面的链接下载,其中包含两个文件:debug.hdebug.cpp。要使用它们,只需将这两个文件添加到你的项目的头文件和源代码目录中,并在你的项目的 stdafx.h 中添加 #include "debug.h" 指令。

debug.h 中,我已经添加了必要的定义和包含文件以启用调试。DBG 类声明如下:

#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 , ... );
};

要使用 DBG 类,你只需创建该类的对象并使用其函数。以下是一些简单的代码片段,说明了如何使用 DBG 类:

#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>

请注意,我的 DbgPrint() 只支持 %d%c%s%f 格式说明符,因为我只在 DbgPrint() 函数的 unionswitch 语句中定义了这些,如下所示。当然,你可以轻松添加其他格式说明符或删除任何不需要的说明符。

#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 );
}

关注点

以这里提供的代码为起点,任何感兴趣的人都可以创建自己的调试类。

© . All rights reserved.