본문으로 바로가기

Implementing the __FUNCTION__ Macro in VC++ 6.0

category 개발언어/c++ 2016. 7. 16. 18:42


VC6.0에서도 __FUNCTON__ 매크로 소스


C++ 개발하다보면 trace printf 등을 이용해서 Bebug를 할때가 많습니다..

이때 어떤 class의 어떤 method에서 호출된 trace printf인지를 판독하기 위해 코드상에 직접 class method의 이름을 입력하게 되죠.. 이런 노가다성 작업을 대신 해 줄수 있는 매크로가 __FUNCTION__, __LINE__, __FILE__ 매크로입니다.

void CTcp_testDlg::OnButton2() 
{
     TRACE("
IMFONE - CTcp_testDlg::OnButton2::line( 0 )Traced......\n ");
     TRACE("%s:line( %d )Traced...... \n", __FUNCTION__, __LINE__);
}
// Output
// IMFONE - CTcp_testDlg::OnButton2::line( 0 )Traced...... 
// IMFONE - CTcp_testDlg::OnButton2::line( 712 )Traced...... 


근데 불행하게도 가장 중요한 __FUNCTION__ 매크로는 VC6.0 이상에만 지원한다고 되어 있더군요.. -.-;;
이리 저리 개발 사이트를 찾아보다 xtrace라는 __FUNCTION__ 매크로를 구현한 소스가 있길레 테스트 해 보았지만 몇가지 오류가 있어 실행되지 않더군요.. 몇가지 수정을 걸쳐 잘 돌아가끔 처리 해 놓았습니다..

xtrace.c
에 있는 아래 
APP_NAME 입맛에 맞게 변경하시면 됩니다.
#define APP_NAME "IMFONE - "

head

#ifndef _XTRACE_H_

#define _XTRACE_H_

#if defined(_DEBUG) && defined(WIN32)

#include <windows.h>

#include <tchar.h>

#pragma comment(lib, "imagehlp.lib")

#pragma warning(disable : 4172)                        // returning address of a temp

#define BUFFERSIZE 512

BOOL  InitSymInfo(PCSTR lpszInitialSymbolPath = NULL, BOOL bSysPath = FALSE);

void    InitSymPath(PSTR lpszSymbolPath, PCSTR lpszIniPath, BOOL bSysPath);

BOOL GetFuncInfo(ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol);

LPCTSTR GetFuncName();

BOOL  KillSymInfo();

static CHAR lpszLast[ BUFFERSIZE ];

#define __FUNCTION__ GetFuncName()

#else

//BOOL InitSymInfo(PCSTR) { return TRUE; };

//BOOL KillSymInfo() {  return TRUE;  };

#define __FUNCTION__ _T("")

#endif

#endif

cpp



#include "stdafx.h"

#include <stdio.h>

#include <windows.h>

#include <tchar.h>

#include <ImageHlp.h>

#include "xtrace.h"

#define APP_NAME "IMFONE - "

#ifdef _DEBUG

void PCSTR2LPTSTR(PCSTR lpszIn, LPTSTR lpszOut)

{

#if defined(UNICODE) || defined(_UNICODE)

          ULONG index = 0;

          PCSTR lpAct = lpszIn;

          for(;; lpAct++)

          {

                   lpszOut[index++] = (TCHAR)(*lpAct);

                   if (*lpAct == 0) break;

          }

#else

          strcpy(lpszOut, lpszIn);

#endif

}

void InitSymPath(PSTR lpszSymbolPath, PCSTR lpszIniPath, BOOL bSysPath)

{          CHAR lpszPath[BUFFERSIZE] = "";

          CHAR lpszTemp[BUFFERSIZE] = "";

          // create the default path

          strcpy(lpszSymbolPath, ".;");

          // get the current path

          sprintf(lpszTemp, __FILE__);

          strcpy(lpszPath, strrev(strchr(strrev(lpszTemp), '\\')));

          strcat(lpszPath, "Debug");

          strcat(lpszSymbolPath, lpszPath);

          if (bSysPath)

          {

                   // environment variable _NT_SYMBOL_PATH

                   if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE))

                   {

                           strcat(lpszSymbolPath, ";");

                             strcat(lpszSymbolPath, lpszPath);

                   }

                    // environment variable _NT_ALTERNATE_SYMBOL_PATH

                   if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE))

                   {

                             strcat(lpszSymbolPath, ";");

                             strcat(lpszSymbolPath, lpszPath);

                   }            


                   // environment variable SYSTEMROOT

                  if (GetEnvironmentVariableA("SYSTEMROOT", lpszPath, BUFFERSIZE))

                   {

                             strcat(lpszSymbolPath, ";");

                             strcat(lpszSymbolPath, lpszPath);                      


                             // SYSTEMROOT\System32

                             strcat(lpszSymbolPath, ";");

                             strcat(lpszSymbolPath, lpszPath);

                             strcat(lpszSymbolPath, "\\System32");

                   }

          }

    


          // Add any user defined path

          if (lpszIniPath != NULL)

          {

                   if (lpszIniPath[0] != '\0')

                   {

                             strcat(lpszSymbolPath, ";");

                             strcat(lpszSymbolPath, lpszIniPath);

                   }

          }

}


BOOL InitSymInfo(PCSTR lpszInitialSymbolPath, BOOL bSysPath)

{

          CHAR  lpszSymbolPath[BUFFERSIZE];

          DWORD        symOptions = SymGetOptions();       

          symOptions |= SYMOPT_DEFERRED_LOADS;

          symOptions &= ~SYMOPT_UNDNAME;       

          SymSetOptions(symOptions);         

          InitSymPath(lpszSymbolPath, lpszInitialSymbolPath, bSysPath);   

          return SymInitialize(GetCurrentProcess(), lpszSymbolPath, TRUE);

}

BOOL GetFuncInfo(ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol)

{

          BOOL ret = FALSE;   

          DWORD dwDisp = 0, dwSymSize = 10000; 

          TCHAR lpszUDSymbol[BUFFERSIZE] = _T("?");      

          CHAR lpszANSIUDSymbol[BUFFERSIZE] = "?";            

          PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, dwSymSize);

          ZeroMemory(pSym, dwSymSize);   

          pSym->SizeOfStruct  = dwSymSize;

          pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);

          // Set the default to unknown

         _tcscpy(lpszSymbol, _T("?"));

          // Get symbol info

          if (SymGetSymFromAddr(GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym))

          {

                   // Make the symbol readable for humans

                   UnDecorateSymbolName(pSym->Name,

                 lpszANSIUDSymbol,

                  BUFFERSIZE,

                 UNDNAME_COMPLETE   |

                UNDNAME_NO_THISTYPE | UNDNAME_NO_SPECIAL_SYMS|UNDNAME_NO_MEMBER_TYPE |

                UNDNAME_NO_MS_KEYWORDS |  UNDNAME_NO_ACCESS_SPECIFIERS |

                                                                    UNDNAME_NO_ARGUMENTS);

                   // Symbol information is ANSI string

                   PCSTR2LPTSTR(lpszANSIUDSymbol, lpszUDSymbol);

                   lpszSymbol[0] = _T('\0');

                   _tcscat(lpszSymbol, lpszUDSymbol);

                   ret = TRUE;

          }

          GlobalFree(pSym);

          return ret;

}

LPCTSTR GetFuncName()

{

          BOOL  bResult = FALSE;

          STACKFRAME callStack;

          TCHAR lpszFnInfo[BUFFERSIZE];

          HANDLE hProcess = GetCurrentProcess();

          HANDLE hThread   = GetCurrentThread();

          CHAR* lpszToken ;

          int size = 0;

          // initialize a stack frame struct in preparation to walk the stack

          ZeroMemory(&callStack, sizeof(callStack));

__asm

{

          call     getEIP;

          getEIP:

          pop          callStack.AddrPC.Offset;

          mov          callStack.AddrStack.Offset, Esp;

          mov          callStack.AddrFrame.Offset, Ebp;

} 


          callStack.AddrPC.Mode         = AddrModeFlat;

          callStack.AddrStack.Mode   = AddrModeFlat;

          callStack.AddrFrame.Mode   = AddrModeFlat;

          // obtain a stack trace of the calling function (i.e., omit this one)

          for (ULONG n = 0; n < 2; n++)

          {

                   bResult = StackWalk(IMAGE_FILE_MACHINE_I386,

                   hProcess,

                   hThread,

                   &callStack,

                   NULL,

                   NULL,

                   SymFunctionTableAccess,

                   SymGetModuleBase,

                   NULL);

          }


          if (bResult && callStack.AddrFrame.Offset != 0) 

          {

                  memset( lpszLast, 0, sizeof( lpszLast ));

                   GetFuncInfo(callStack.AddrPC.Offset, callStack.AddrFrame.Offset, lpszFnInfo);

                   lpszToken = strtok(lpszFnInfo, "::");

                   if ( lpszToken != NULL )

                   {

                             strcpy(lpszLast, APP_NAME);      

                   }

                   while (lpszToken != NULL)

                   {

                             strcat(lpszLast, lpszToken);

                             strcat(lpszLast, "::");

                             lpszToken = strtok(NULL, "::");

                   }

                   size = strlen( lpszLast );

                   lpszLast[ size -1 ] = '\x00';

                   //strcat(lpszLast, ":"); 

                   return lpszLast;

          }

          return "";

}

BOOL KillSymInfo()

          return SymCleanup(GetCurrentProcess());

}

#endif

#ifndef _MANUAL_INIT

class InitXTrace {

public:

    InitXTrace()

     {

#if defined(_DEBUG) && defined(WIN32)

                    InitSymInfo(NULL);

#endif

     }

} initXTrace;

#endif // #ifndef _MANUAL_INIT


'개발언어 > c++' 카테고리의 다른 글

메일전송,Mail,SEND  (0) 2016.07.16
동적인 메모리 디버깅하기  (0) 2016.07.16
Memory(-Leak) and Exception Trace (CRT and COM Leaks)  (0) 2016.07.16
메모리누수(leak) 탐지소스  (0) 2016.07.16
윈도우 시스템 정보 얻기  (0) 2016.07.16