您的位置:首页 > 编程语言 > C语言/C++

C++出现exception异常的位置如何定位?

2010-10-26 09:09 926 查看
有人问过我,在windows系统,如果C++的new产生异常exception,怎么才能知道出错的位置。



最简单的 方法是用 _set_new_handler。



如果不是 new 产生的, 或者程序非法访问内存了。



经过试验,可以先用__try __except捕获它,

在处理函数里面输出callstack调用堆栈,以及exe、dll的名字、地址、范围等信息。

处理完了返回EXCEPTION_CONTINUE_SEARCH,交给C++的try catch来继续处理。









#include <windows.h>

#include <stdio.h>





class win32_tool_help

{

public:


win32_tool_help();


virtual ~win32_tool_help();




static int show_module_list();

};





#include <tlhelp32.h>

#include <tchar.h>





//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////



win32_tool_help::win32_tool_help()

{



}



win32_tool_help::~win32_tool_help()

{



}



int win32_tool_help::show_module_list()

{


HANDLE hSnap = CreateToolhelp32Snapshot(


TH32CS_SNAPMODULE,


GetCurrentProcessId( )


);




MODULEENTRY32 me;




me.dwSize = sizeof(me);




BOOL ret = Module32First( hSnap, &me );




while (TRUE == ret)


{


_tprintf(


TEXT("hModule = %p, modBaseAddr = %p, modBaseSize = %08X, ")


TEXT("szExePath = %s, szModule = %s /n"),


me.hModule,
me.modBaseAddr,
me.modBaseSize,


me.szExePath, me.szModule


);




ret = Module32Next( hSnap, &me );


}




CloseHandle( hSnap );




return 0;

}







class win32_stack_walk

{

public:


win32_stack_walk();


virtual ~win32_stack_walk();




static int start( LPEXCEPTION_POINTERS ep );



};







#include <imagehlp.h>



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



//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////



win32_stack_walk::win32_stack_walk()

{



}



win32_stack_walk::~win32_stack_walk()

{



}



int win32_stack_walk::start( LPEXCEPTION_POINTERS ep )

{


const DWORD machine_type = IMAGE_FILE_MACHINE_I386;


HANDLE hProcess, hThread;




hProcess = GetCurrentProcess();


hThread = GetCurrentThread();




STACKFRAME frame = {0};




LPVOID ContextRecord = NULL;




PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine = NULL; // &ReadProcessMemory;


PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine = &SymFunctionTableAccess;


PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine = &SymGetModuleBase;


PTRANSLATE_ADDRESS_ROUTINE TranslateAddress = NULL;




BOOL ret = FALSE;




struct handle_frame_addr {




static


void set( ADDRESS& addr_s, DWORD addr )


{


addr_s.Mode = AddrModeFlat;


addr_s.Segment = 0;


addr_s.Offset = addr;


}




static


DWORD get( const ADDRESS& addr_s )


{


return addr_s.Offset;


}


};




handle_frame_addr::set( frame.AddrStack , ep->ContextRecord->Esp );


handle_frame_addr::set( frame.AddrFrame , ep->ContextRecord->Ebp );


handle_frame_addr::set( frame.AddrPC , ep->ContextRecord->Eip );


handle_frame_addr::set( frame.AddrReturn, 0 );




do


{




printf( "Stack = %08X Frame = %08X PC = %08X Return = %08X /n",


handle_frame_addr::get( frame.AddrStack ),


handle_frame_addr::get( frame.AddrFrame ),


handle_frame_addr::get( frame.AddrPC ),


handle_frame_addr::get( frame.AddrReturn )


);




ret = StackWalk( machine_type, hProcess, hThread,


&frame,


ContextRecord,


ReadMemoryRoutine,


FunctionTableAccessRoutine,


GetModuleBaseRoutine,


TranslateAddress );




} while( ret == TRUE );




return 0;

}





#define SHOW_ESP() /


do { /


DWORD reg_esp = 0; /


__asm { /


mov reg_esp, esp /


} /


printf("esp = %08X/n", reg_esp); /


printf("ep->Esp = %08X/n", ep->ContextRecord->Esp); /


}while(0);







void show_diag_info( LPEXCEPTION_POINTERS ep )

{


win32_stack_walk::start( ep );


win32_tool_help::show_module_list();

}





void raise01( )

{


printf("%s/n", "raise");




CONTEXT ctx_s = {0};


EXCEPTION_POINTERS ep_s;


LPEXCEPTION_POINTERS ep = &ep_s;


ep_s.ContextRecord = &ctx_s;




SHOW_ESP();




memset( 0, 1, 1 );



}



void raise02( )

{


printf("%s/n", "raise");




CONTEXT ctx_s = {0};


EXCEPTION_POINTERS ep_s;


LPEXCEPTION_POINTERS ep = &ep_s;


ep_s.ContextRecord = &ctx_s;




SHOW_ESP();








throw -1;



}

int seh_filter01( DWORD ec, LPEXCEPTION_POINTERS ep )

{


printf("%s/n", "seh_filter");




SHOW_ESP();




show_diag_info( ep );




return EXCEPTION_EXECUTE_HANDLER;

}



int seh_filter02( DWORD ec, LPEXCEPTION_POINTERS ep )

{


printf("%s/n", "seh_filter");




SHOW_ESP();




show_diag_info( ep );




return EXCEPTION_CONTINUE_SEARCH;

}



void test01()

{


DWORD ec = 0;


LPEXCEPTION_POINTERS ep = NULL;


__try


{


raise01();


}


__except( ec = GetExceptionCode(), ep = GetExceptionInformation(), seh_filter01( ec, ep ) )


{


printf("%s/n", "test01->__except");


SHOW_ESP();


}



}



void test02_inner()

{


DWORD ec = 0;


LPEXCEPTION_POINTERS ep = NULL;




__try


{


raise02();


}


__except( ec = GetExceptionCode(), ep = GetExceptionInformation(), seh_filter02( ec, ep ) )


{


printf("%s/n", "test01->__except");


SHOW_ESP();


}

}



void test02()

{




try


{


test02_inner();


}


catch(...)


{


printf("%s/n", "C++ catch(...)");


}



}





int main(int argc, char* argv[])

{


test01();


test02();




return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐