C/C++ call stack traces

哎,郁闷,不知道是CSDN的bug还是有人故意捣乱,辛辛苦苦写的文章被替换成“自由的思维”一文,真是百思不解呀,至此也没有什么再写的激情了!(该程序能输出调用栈上的函数名称,实参个数及其值,以及函数调用处的偏移量。像VC++ 6.0中的call stack)

控制台输出如下:

StackTrace dump begin...

StackTrace(  )
Call_C( 
0x0000000A 0x00000014  )        line  448   +   0  bytes
Call_B( 
0x0000000A 0x00000014  )        line  453   +   13  bytes
Call_A( 
0x0000000A 0x00000014  )        line  458   +   13  bytes
main( 
0x00000001 0x00391380 0x003913D8  )      line  463   +   9  bytes

StackTrace dump end
!
Press any key to 
continue

 有篇文章特好,Playing with the  stack : http://www.codeguru.com/cpp/misc/misc/stack/article.php/c3875/

 下面贴个源码。

#include  < stdio.h >
#include 
< windows.h >
#include 
< Dbghelp.h >

#define  JMP_INSTR 0xE9
#define  SYM_BUFF_SIZE 512

static  BYTE g_stSymbol [ SYM_BUFF_SIZE ] ;

int  GetFuncArgsNum( int  retAddrs)
{
    
if(0xC483 == *(WORD *)retAddrs) // 0xC483 'Add esp, xxx'
        return *(BYTE*)(retAddrs + 2>> 2;
    
else
        
return 0;
}


int  GetFuncArgVal( int  ebp,  int  index)
{
    
return *(int *)(ebp + ((index + 2<< 2));
}


int  GetCallFuncAddrs( int  retAddrs)
{
    
int callFuncAddrs = *(int *)(retAddrs - 4+ retAddrs;
    
    
//callFuncAddrs > 0x80000000 can cause the 'can not read the memory' error!
    if((DWORD)callFuncAddrs > 0x80000000)
    
{
        
return 0;
    }

    
    
//Jump over the JMP instruction to the real address of function
    while(JMP_INSTR == *(BYTE *)callFuncAddrs) 
    
{
        
int offset = callFuncAddrs + 1;
        callFuncAddrs 
= *(int *)(offset) + (callFuncAddrs + 5);
    }


    
return callFuncAddrs;
}


void  PrintCallFuncOffset( int  retAddrs)
{
    HANDLE hCurProcess 
= (HANDLE) ::GetCurrentProcessId();
    
static saved_retAddrs = 0;

    
if(0 == saved_retAddrs)
    
{
        saved_retAddrs 
= retAddrs;
        printf(
"%s"" ");
        
return;
    }


    DWORD dwDisp;
    IMAGEHLP_LINE stLine;

    FillMemory(
&stLine, NULL, sizeof(IMAGEHLP_LINE));
    stLine.SizeOfStruct 
= sizeof(stLine);
    
if(!::SymGetLineFromAddr(hCurProcess, (DWORD)saved_retAddrs, &dwDisp, &stLine))
    
{
        printf(
"%s"" ");
        
return;
    }


    printf(
"line %d + %d bytes ", stLine.LineNumber, dwDisp);
    saved_retAddrs 
= retAddrs;
}


void  PrintCallFunc( int  ebp)
{
    
int callFuncAddrs;
    DWORD dwDisp 
= 0;
    
int retAddrs = *(int *)(ebp + 4);
    HANDLE hCurProcess 
= (HANDLE) ::GetCurrentProcessId();
    PIMAGEHLP_SYMBOL pSym 
= (PIMAGEHLP_SYMBOL)&g_stSymbol ;
    
int argsNum = ::GetFuncArgsNum(retAddrs);

    callFuncAddrs 
= GetCallFuncAddrs(retAddrs);
    
if(!::SymGetSymFromAddr(hCurProcess, (DWORD)callFuncAddrs, &dwDisp, pSym))
    
{
        
return;
    }

    
    
//Print the name of call function
    printf("%s( ", pSym->Name);
    
    
//Print the args
    if(argsNum > 0)
    
{
        argsNum
--;
        
for(int i = 0; i < argsNum; i++)
        
{
            printf(
"0x%08X, ", GetFuncArgVal(ebp, i));
        }


        
//print the last arg.
        printf("0x%08X ) ", GetFuncArgVal(ebp, i));
    }

    
else
    
{
        printf(
"%s"" ) ");
    }


    
//Print the line number
    PrintCallFuncOffset(retAddrs);
}


void  StackTrace( void )
{
    
int saved_ebp;
    
int cur_ebp;
    HANDLE hCurProcess;

    
//Fill the IMAGEHLP_SYMBOL struct
    PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&g_stSymbol ;
    FillMemory ( pSym , NULL , SYM_BUFF_SIZE ) ;
    pSym
->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL ) ;
    pSym
->MaxNameLength = SYM_BUFF_SIZE - sizeof ( IMAGEHLP_SYMBOL );

    
//Initialize & load the symbol table
    hCurProcess = (HANDLE)::GetCurrentProcessId();
    ::SymSetOptions ( SYMOPT_UNDNAME 
| SYMOPT_LOAD_LINES ) ;
    
if(!::SymInitialize(hCurProcess, NULL, TRUE))// Load the module automatically
    {
        
return;
    }


    __asm
    
{
        
//Get the current ebp
        mov cur_ebp, ebp
    }


    
//Get the saved ebp
    saved_ebp = *(int *)cur_ebp;

    
//Print the call stack
    printf("StackTrace dump begin... ");
    
while(saved_ebp != 0)
    
{
        PrintCallFunc(cur_ebp);

        
//Move to the next caller's stack frame
        cur_ebp = saved_ebp;
        saved_ebp 
= *(int *)saved_ebp;
    }


    printf(
" StackTrace dump end! ");
    ::SymCleanup(hCurProcess);
}


class  CTest
{
public:
    
void Hello()
    
{
        StackTrace();
    }
;
}
;

int  Call_C( int  a,  int  b)
{
    StackTrace();
    
return (a + b);
}


int  Call_B( int  a,  int  b)
{
    
return Call_C(a, b);
}


int  Call_A( int  a,  int  b)
{
    
return Call_B(a, b);
}


main()
{
    Call_A(
1020);
//    CTest test;
//    test.Hello();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值