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 |