C++出现exception异常的位置如何定位?
来源:互联网 发布:中国农村数据库 编辑:程序博客网 时间:2024/05/16 05:32
有人问过我,在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;
}
- C++出现exception异常的位置如何定位?
- Locating the postion of exception 定位异常的位置
- 程序异常立刻退出,如何定位关键代码位置
- SURF角点检测出现错误:SURF.exe 中的 0x756ad36f 处未处理的异常: Microsoft C++ 异常: 内存位置 0x003fcaf0 处的 cv::Exception。
- Exception-异常处理(c++)的总结
- 如何定位导致Crash的代码位置
- 如何定位导致Crash的代码位置
- 如何定位导致Crash的代码位置
- 如何定位导致Crash的代码位置
- 如何定位导致Crash的代码位置
- C语言文件位置标记的定位
- VS2017出现: Microsoft C++ 异常: cv::Exception,位于内存位置 0x000000D99016F6B0 处。
- Exception异常类(C#)
- iOS开发------使用Xcode编译器定位抛出异常的位置
- window 安装MongoDB 出现的exception:connect failed 异常
- 如何定位异常
- 百度定位SDK只定位一次以及系统没有出现位置服务图标的解决
- ARM调试中的出现异常的定位方法
- struts2马士兵笔记
- 计算机会计信息系统中暂估存货的处理方法研究
- 有挑战的地方就有机会
- 双色球Java模拟
- jar包详解和META-INF作用
- C++出现exception异常的位置如何定位?
- XML文档的操作
- ASP.NET 项目安装包制作(二)数据库安装、其他组件的安装
- JavaScript操作XML文档
- php date("Y-m-d G:i T",time()) 取出来的时间和本地时间老差8个小时
- Android XML解析学习——Sax方式
- 判断是否为数组
- patch 打补丁程序和diff
- mysql终于配置好了