#include <windows.h>
#include <stdio.h>
#include "dbghelp.h"#pragma comment( lib, "dbghelp.lib" )void dump_callstack( CONTEXT *context )
{
STACKFRAME sf;
memset( &sf, 0, sizeof( STACKFRAME ) );

sf.AddrPC.Offset = context->Eip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = context->Esp;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = context->Ebp;
sf.AddrFrame.Mode = AddrModeFlat;

DWORD machineType = IMAGE_FILE_MACHINE_I386;

HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();

for( ; ; )
{
if( !StackWalk(machineType, hProcess, hThread, &sf, context, 0, SymFunctionTableAccess, SymGetModuleBase, 0 ) )
{
break;
}

if( sf.AddrFrame.Offset == 0 )
{
break;
} BYTE symbolBuffer[ sizeof( SYMBOL_INFO ) + 1024 ];
PSYMBOL_INFO pSymbol = ( PSYMBOL_INFO ) symbolBuffer;

pSymbol->SizeOfStruct = sizeof( symbolBuffer );
pSymbol->MaxNameLen = 1024;

printf( " Function:  0x%X \n", sf.AddrPC.Offset ); DWORD64 symDisplacement = 0;
if( SymFromAddr( hProcess, sf.AddrPC.Offset, 0, pSymbol ) )
{
printf( "Function : %s ", pSymbol->Name );
}
else
{
printf( "SymFromAdd failed! LastErrorCode:%d\n", GetLastError() );
}

IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
DWORD dwLineDisplacement;

if( SymGetLineFromAddr( hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo ) )
{
printf( "[Source File : %s Line: %u] ", lineInfo.FileName, lineInfo.LineNumber );  
}
else
{
printf( "SymGetLineFromAddr failed! " );
}
}
}DWORD excep_filter( LPEXCEPTION_POINTERS lpEP )
{
/**//// init dbghelp.dll
if( SymInitialize( GetCurrentProcess(), NULL, TRUE ) )
{
printf( "Init dbghelp ok.\n" );
}

dump_callstack( lpEP->ContextRecord );

if( SymCleanup( GetCurrentProcess() ) )
{
printf( "Cleanup dbghelp ok.\n" );
}

return EXCEPTION_EXECUTE_HANDLER;
}void func1( int i )
{
int *p = 0;
*p = i;
}void func2( int i )
{
func1( i - 1 );
}void func3( int i )
{
func2( i - 1 );
}void test( int i )
{
func3( i - 1 );
}int main()
{
__try
{
test( 10 );
}
__except( excep_filter( GetExceptionInformation() ) )
{
printf( "Some exception occures.\n" );
}

return 0;
}
以上代码在命令行中编译 cl test.cpp /Od /Zi 
结果运行正常.但是我新建一个工程(去掉了相关的优化选项),编译后,
SymFromAddr 等API会失败, LastErrorCode 是 487请问该如何解决?

解决方案 »

  1.   

    pdb文件没有生成,所以SymFromAddr 等API会失败。
    新建的工程把它打开即可。
      

  2.   

    我已经设置工程生成 .pdb 文件了,
    试了多次,只要是在工程里面生成的,就会出错。
      

  3.   

    dbghelp版本比解析的pdb格式要老?还是pdb文件不在搜索目录下?
    新的dbghelp建议StackWalk64替换StackWalk函数。
      

  4.   


    但为什么, 以上代码在命令行中编译 cl test.cpp /Od /Zi 
    结果运行正常. 
      

  5.   

    不太清楚,是不是命令行中cl.exe的路径和IDE的路径搜索顺序不一样?