VC6中实现__FUNCTION__(VC6 在函数体内获取函数名)

这篇文章综合了我在网上找到的一些相关文章这里整理一下:

 

  在VC6以后的VS版本中可以在函数体内 通过 __FUNCSIG__ 等方式获取函数的名字;

但是在VC6中要自己实现,以下是我找到的方法:

方法1:

#pragma once
#include <windows.h>
typedef unsigned long ULONG_PTR,*PULONG_PTR;
#define __out_ecount_opt(x)
#include <dbghelp.h>
#include <stdio.h>

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

static LPSTR GetSymbolSearchpath ()
{
    char   directory [MAX_PATH];
    char   drive [MAX_PATH];
    HMODULE module;
    LPSTR  path = new char [MAX_PATH];
    memset(path,0,MAX_PATH * sizeof(path[0]));
    // Oddly, the symbol handler ignores the link to the PDB embedded in the
    // executable image. So, we'll manually add the location of the executable
    // to the search path since that is often where the PDB will be located.
    path[0] = '\0';
    module = GetModuleHandle(NULL);
    GetModuleFileNameA(module, path, MAX_PATH);
    _splitpath(path, drive, directory, NULL, 0);
    strcpy(path, drive);
    strcat(path, directory);
    // Append the working directory.
    strcat(path, ";.\\");
   
    return path;
}

class mydbg
{
public:
    mydbg(DWORD dwAddr)
    {
        memset(szFuctionName,0,sizeof(szFuctionName));
        BYTE  symbolBuffer [sizeof(SYMBOL_INFO) + 256 * sizeof(CHAR)] = { 0 };
        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) &symbolBuffer;
        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        pSymbol->MaxNameLen = 256;
        if( SymFromAddr( GetCurrentProcess(),dwAddr, 0, pSymbol ) )
        {
           strcpy(szFuctionName, pSymbol->Name);
        }
        else
        {
           printf("SymFromAddr Failed! %d\n",GetLastError());
        }
    }
    CHAR szFuctionName[32];
};
#define INIT_SYM(fInvadeProcess) \
    LPSTR symbolpath = GetSymbolSearchpath();\
    SymInitialize( GetCurrentProcess(), symbolpath, fInvadeProcess); \
    delete[] symbolpath;
#define UNINIT_SYM() \
    SymCleanup(GetCurrentProcess());

static DWORD GetEIP()
{
    DWORD dwCallerAddr;
    __asm
    {
    push DWORD  ptr[ebp+4]
    pop  DWORD  ptr[dwCallerAddr]
    sub  DWORD  ptr[dwCallerAddr],5 //减去 call GetEIP() 的长度
    }
    return dwCallerAddr;
}


#define __func_for_vc6__ (mydbg(GetEIP()).szFuctionName)

 

C/C++ code
    
    
    
    
// test.cpp #include " stdafx.h " //#include " stdlib.h " #include " dbghelpapi.h " //#pragma comment(lib,"dbghelp.lib") int main( int argc, char * argv[]) { INIT_SYM(TRUE) printf( " this is <%s> fuction\n " ,__func_for_vc6__); UNINIT_SYM() return 0 ; }


output:
this is <main> fuction

说明
release 下必须在设置里选中 "产生调试信息"选项

copy C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib下的DbgHelp.Lib到当前文件夹下;

 

方法二:http://www.codeproject.com/KB/debug/extendedtrace.aspx      

方法三:http://www.codeproject.com/KB/tips/xtrace.aspx  

方法二和三基本属于同一种方法,在我的机器上(win7 + VC6 )没有得到预期;

 

方法四:就是在 VC 中 编写一个 DLL ,这个DLL可以返回当前的函数名(当然是利用现成的__FUNCSIG__),通过VC6 调用这个DLL中的函数获取VC6中的函数名;              

你可能感兴趣的:(VC6中实现__FUNCTION__(VC6 在函数体内获取函数名))