給函數增加Debug頭 – windows平台的普通列印調試處理

來源:互聯網
上載者:User

     筆者在VS2008和VC6.0兩種常用平台應用此工具,發現VC6.0版本不支援__FUNCTION__宏,有高手自訂的__FUNCTION__實現在此。

     有幾個問題需要注意:

1、在MFC環境下報錯的問題:

①#error WINDOWS.H already included.  MFC apps must not #include <windows.h>。無奈的解決方案是把自動添加上的調試標頭檔#include語句添加到afx相關的標頭檔之後。

②unexpected endif:需要添加stafx.h的先行編譯標頭檔,然後把xtrace.cpp裡的#if defined(_DEBUG) && defined(WIN32)和對應的#endif去掉

2、在Unicode環境下報錯的問題:

添加強制轉換


最終的xtrace.cpp檔案代碼如下:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * xtrace.cpp by Hector J. Rivas, torjo2k@hotmail.com from "ExtendedTrace" * by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com *  * A Win32 VC++ 6.0 implementation of the __FUNCTION__ macro that works for me. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */#include "StdAfx.h"#include <stdio.h>#include <windows.h>#include <tchar.h>#include <ImageHlp.h>#include "xtrace.h"// Unicode safe char* -> TCHAR* conversionvoid 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;} #elsestrcpy(lpszOut, lpszIn);#endif}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * InitSymPath(): figure  out  the  path for the symbol files; the search path is: * * . + *__FILE__ (path) + Debug + * %_NT_SYMBOL_PATH% + * %_NT_ALTERNATE_SYMBOL_PATH% + * %SYSTEMROOT% + * %SYSTEMROOT%\System32 + * lpszIniPath * * NOTES: There is no size check for lpszSymbolPath. If you want to limit the macro to * symbols in your debug executable, you can omit the environment variables (default). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */void InitSymPath(PSTR lpszSymbolPath, PCSTR lpszIniPath, BOOL bSysPath){CHAR lpszPath[BUFFERSIZE] = "";CHAR lpszTemp[BUFFERSIZE] = "";// create the default pathstrcpy(lpszSymbolPath, ".;");// get the current pathsprintf(lpszTemp, __FILE__);strcpy(lpszPath, strrev(strchr(strrev(lpszTemp), '\\')));strcat(lpszPath, "Debug");strcat(lpszSymbolPath, lpszPath);if (bSysPath){// environment variable _NT_SYMBOL_PATHif (GetEnvironmentVariableA("_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);}// environment variable _NT_ALTERNATE_SYMBOL_PATHif (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);}// environment variable SYSTEMROOTif (GetEnvironmentVariableA("SYSTEMROOT", lpszPath, BUFFERSIZE)){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);// SYSTEMROOT\System32strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszPath);strcat(lpszSymbolPath, "\\System32");}}// Add any user defined pathif (lpszIniPath != NULL){if (lpszIniPath[0] != '\0'){strcat(lpszSymbolPath, ";");strcat(lpszSymbolPath, lpszIniPath);}}}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * InitSymInfo(): initializes the symbol files * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */BOOL InitSymInfo(PCSTR lpszInitialSymbolPath, BOOL bSysPath){CHARlpszSymbolPath[BUFFERSIZE];DWORDsymOptions = SymGetOptions();// set current image help API options; according to the SDK docs, with// SYMOPT_DEFERRED_LOADS: "Symbols are not loaded until a reference is made// requiring the symbols be loaded. This is the fastest, most efficient way to use// the symbol handler.". SYMOPT_UNDNAME is excluded to do the undecoration// ourselves.symOptions |= SYMOPT_DEFERRED_LOADS; symOptions &= ~SYMOPT_UNDNAME;SymSetOptions(symOptions);// get the search path for the symbol filesInitSymPath(lpszSymbolPath, lpszInitialSymbolPath, bSysPath);return SymInitialize(GetCurrentProcess(), lpszSymbolPath, TRUE);}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * GetFuncInfo(): Get function prototype from address and stack address * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */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 infoif (SymGetSymFromAddr(GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym)){// Make the symbol readable for humansUnDecorateSymbolName(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 stringPCSTR2LPTSTR(lpszANSIUDSymbol, lpszUDSymbol);lpszSymbol[0] = _T('\0');_tcscat(lpszSymbol, lpszUDSymbol);   ret = TRUE;}GlobalFree(pSym);return ret;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * GetFuncName(): return the undecorated function name * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */LPCTSTR GetFuncName(){BOOL           bResult = FALSE;STACKFRAME     callStack;CONTEXT        context;TCHAR          lpszFnInfo[BUFFERSIZE];HANDLE         hProcess = GetCurrentProcess();HANDLE         hThread  = GetCurrentThread();// initialize a context struct to retrieve processor-specific register dataZeroMemory(&context, sizeof(context));context.ContextFlags = CONTEXT_FULL;if (!GetThreadContext(hThread, &context))return L"";// initialize a stack frame struct in preparation to walk the stackZeroMemory(&callStack, sizeof(callStack));callStack.AddrPC.Offset    = context.Eip;callStack.AddrStack.Offset = context.Esp;callStack.AddrFrame.Offset = context.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) {GetFuncInfo(callStack.AddrPC.Offset, callStack.AddrFrame.Offset, lpszFnInfo);// from now on its all personal display preferences with string manipulation// tokenize the undecorated returned symbol to omit the class nameCHAR* lpszToken = strtok((char *)lpszFnInfo, "::");CHAR  lpszLast[BUFFERSIZE] = "";while (lpszToken != NULL){strcpy(lpszLast, lpszToken);lpszToken = strtok(NULL, "::");}// append a delimiter, so that our display in printf instructions is // 'functionname: message' for debug builds and 'message' for release builds,// using the format string "%smessage" and __FUNCTION__ as an argumentstrcat(lpszLast, ": ");return (const unsigned short *)lpszLast;}return L"";}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * KillSymInfo(): uninitialize the loaded symbol files * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */BOOL KillSymInfo() { return SymCleanup(GetCurrentProcess()); }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.