在程序中得到本函数得名称.

six2me 2007-04-06 03:20:55

我在程序中需要实现以下功能.
在不同得函数中调用通用得方法,得到正在运行得函数得名称.

假设,这个方法叫 FUNC_CUST()

使用.
void AA()
{
TRACE("%s",FUNC_CUST());
}
void BB()
{
TRACE("%s",FUNC_CUST());
}

我在网络上找到一个 "__FUNCTION__"得,说可以实现这个功能.但是在vs.net上面行,在vc6中不能使用.也有通过其他方法实现得.我找到了一个,只能输出一个NULL,

最好有实现得具体例子.
分数不够可以继续加.
...全文
514 32 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
six2me 2007-04-14
  • 打赏
  • 举报
回复
暂时结贴,谁有什么好的方法,可以给我发邮件.meto6@163.com
six2me 2007-04-09
  • 打赏
  • 举报
回复
ringphone(临风)
能不能说说你得到得函数信息得过程阿.
我得计算机得配置是.P4D2.66.windows2003+sp1.
我觉得可能和计算机又关系了.
我调试到 if (bResult && callStack.AddrFrame.Offset != 0)
这里就直接退出了.

把代码部分贴到这里,希望高手们指教.
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 data
ZeroMemory(&context, sizeof(context));

context.ContextFlags = CONTEXT_FULL;

if (!GetThreadContext(hThread, &context))
return "";

// initialize a stack frame struct in preparation to walk the stack
ZeroMemory(&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 name
CHAR* lpszToken = strtok(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 argument
strcat(lpszLast, ": ");

return lpszLast;
}

return "";
}
有兴趣得朋友可以到三楼提示网址下载,共同研究.
youngwolf 2007-04-09
  • 打赏
  • 举报
回复
你放置一个全局变量,每个函数,在第一行中去更改这个变量,在要检测的函数中读取这个值,不就知道运行到哪个函数了?
six2me 2007-04-09
  • 打赏
  • 举报
回复
ringphone(临风)
你说得这个我上面已经提到了(见三楼),只是我没有实现,都是输出NULL.
可能是我得使用有问题.但是我又找不到错误.看看能为高手可以阿.
谢谢了.
ringphone 2007-04-09
  • 打赏
  • 举报
回复
一个可能行得地方(我没有实现,输出NULL).
http://www.codeproject.com/useritems/xtrace.asp
---------------------------------------
调用__FUNCTION__前需要先调用InitSymInfo();
跟踪一下就能看到函数信息了,(类名::函数)格式,但是返回的却又变成了(函数:)格式,看来需要改一下代码。
liuyaoyou 2007-04-09
  • 打赏
  • 举报
回复
好!顶~
chehw 2007-04-09
  • 打赏
  • 举报
回复
1、上面的代码设计初衷是用于DEBUG版的调试,如果没有源代码,即使发现错误也无计可施。

2、上面的代码是随手写的,没做测试,有需要改进的地方。

3、如果希望在无源代码的情况下也有效,若无编译器支持则比较麻烦,需手工生成一个包含所有待显示的函数名的索引表,存放在资源文件或配置文件中,
可自定义配置文件的格式如下:
[FILENAME]:[LINE_NUMBER]=[FUNC_NAME]

重定义__FUNCTION__宏,在DEBUG版时预生成该配置文件,
在RELEASE版时直接从配置文件中读取。
six2me 2007-04-09
  • 打赏
  • 举报
回复
感谢chehw(chehw),设计了另外得一个思路,但是存在以下问题:
1.只能使用于带代码调试,当编译成可执行文件后,文件不存在,不能查找.
2.当代码文件中,有多个函数调用时,会出线定位错误.
six2me 2007-04-09
  • 打赏
  • 举报
回复
不是getlasterror的问题.是执行第二次的时候.callStack.AddrFrame.Offset==0,不能进入if(),直接返回了.
新发现问题.刚才我是一直启动2个vc,现在关掉了,一个,callStack.AddrFrame.Offset竟然<>0了,但是得到的字符串还是不对.一直是这个"KiFastSystemCallRet: ",不明白.555~~~
ringphone 2007-04-09
  • 打赏
  • 举报
回复
第一个参数没什么好改的,Intel机器,32位选IMAGE_FILE_MACHINE_I386,64位选IMAGE_FILE_MACHINE_IA64

我机器是WIN2000,表现正常。看来跟OS有关,第二个循环失败用GetLastError看看是什么错误。
six2me 2007-04-09
  • 打赏
  • 举报
回复
彻底晕了,在4台计算机作实验.
1.windows2003+sp1 P4D 2.66 返回""
2.windows2003+sp1 P4D 3.0 返回""
3.windows2003+sp1 p4 2.4G 能够进去到if()中,返回?
4.windows2000+sp4 p4 1.7G 完全正常,能够得到正确得函数名称.

现在怀疑是stackwalk函数得问题.很有可能是第一个参数.但是看了半天定义文件,不知道修改成那一个.还有我向用stackwalk64函数实验,但是需要包含dbghelp.h,我得计算机上面没有,看看谁可以帮我解决?

急...都郁闷了2天了.
six2me 2007-04-09
  • 打赏
  • 举报
回复
刚才在win2000+sp4下作实验,能够正常返回,郁闷中.我现在怀疑stackwalk函数得第一个参数有问题.看看那位高手可以解决,在线等!!!!!!!!!!!!!!
six2me 2007-04-09
  • 打赏
  • 举报
回复
哦,不好意思,是那个if()判断中得为0,就return ""了.
for (ULONG n = 0; n < 2; n++)
{
bResult = StackWalk(IMAGE_FILE_MACHINE_I386,
hProcess,
hThread,
&callStack,
NULL,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL);
}
在这里第一次循环还可以,result=1,callstack.addframe.offset=1239028
第二次循环result=1,callstack.addframe.offset=0.
下面得if就不能进去了.
ringphone 2007-04-09
  • 打赏
  • 举报
回复
->if (bResult && callStack.AddrFrame.Offset != 0)

到这里再按F10就挂了?难道callStack.AddrFrame.Offset指飞掉了?
chehw 2007-04-06
  • 打赏
  • 举报
回复
lstrcpy(__function__, pszCursor);
hit255 2007-04-06
  • 打赏
  • 举报
回复
听课
chehw 2007-04-06
  • 打赏
  • 举报
回复
另附一个自己扩展的可获取整个函数原型的__FUNCTION__, 为简化代码,省略了相关的错误处理

在任何函数体内的前几行时,可直接用__FUNCTION__得到该函数的完整原型

static char __function__[1024]="";
LPCTSTR GetFunctionDeclare(LPCTSTR szFileName, LONG nLineNumber);
#define __FUNCTION__ GetFunctionDeclare(__FILE__, __LINE__)

LPCTSTR GetFunctionDeclare(LPCTSTR szFileName, LONG nLineNumber)
{
HANDLE hFile;
LPTSTR pszBuffer=NULL;
DWORD dwSize;
hFile=CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE==hFile) return NULL;
dwSize=GetFileSize(hFile, NULL)+1;
pszBuffer=(LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(dwSize));
ReadFile(hFile, pszBuffer, dwSize-1, &dwSize, NULL);
int nLine=0;
LPTSTR pCursor=pszBuffer;
LPTSTR pEnd;
while(nLine<(nLineNumber-1))
{
pCursor=_tcsstr(pCursor, TEXT("\r\n"));
if(NULL==pCursor) return NULL;
pCursor+=2;
nLine++;

}
pEnd=pCursor;

if(pCursor!=pszBuffer)
{
pEnd-=2;
*pEnd=0;
pEnd--;
pCursor=_tcsrchr(pszBuffer, TEXT('}'));
if(NULL!=pCursor)
{
pCursor++;
while(!isalpha(*pCursor) && pCursor<pEnd)
{
pCursor++;
}
pEnd=_tcsstr(pCursor, TEXT("\r\n"));
*pEnd=0;

}
}


LocalFree(pszBuffer);
CloseHandle(hFile);
return __function__;
}
chehw 2007-04-06
  • 打赏
  • 举报
回复
#define TRACE(sz) printf("%s\r\n", sz);
#ifdef _DEBUG
#define F(fn) TRACE(#fn); fn
#else
#define F(fn) fn
#endif



设原调用方法为 aa(x, y, z);
新调用方法为 F(aa)(x,y,z);


six2me 2007-04-06
  • 打赏
  • 举报
回复
akirya:
你的函数体中还是出现了AA的参数了啊,这样没有太大的用处,还不是通用的.
  • 打赏
  • 举报
回复
void AA()
{
printf("%s",typeid(AA).name());
}
加载更多回复(12)

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧