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

 

有人问过我,在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;

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1,pe.zip<br>PE文件是windows(95/98/NT)目前采用的可执行文件格式。流行的CIH病毒就是通过改变PE文件的内容,并且保持文件大小不变,从而实现自己的功能。本程序通过分析PE文件格式,将可执行文件的文件定位表重新定位,指向用户编写的DLL,然后指令指针返回正常调用位置。在DLL中通过系统挂钩,实现了后台各种级别密码的截获功能。COOL! (110KB)<END><br>2,mailchecker.zip<br>关于smptp,pop3,tray 等方面的编程(56KB)<END><br>3,Image.zip<br>TImagePlus 是加强版的 TImage 构件,能够一并储存图像与说明文字於单一文件中 (347KB)<END><br>4,Jandraw.zip<br>TjanDrawImage 是改良版的 TImage 构件,提供超过 100 个以上的绘图画笔样式,50 种以上的显示特效的构件(553KB)<END><br>5,fe500-3.zip<br>文件快车3(166KB)<END><br>6,fe500-2.zip<br>文件快车2(329KB)<END><br>7 ,fe500-1.zip<br>文件快车1(227KB)<END><br>8,catalog.zip<br>扫描磁盘所有文件的例子(2KB)<END><br>9,hexdump.zip<br>读16进制的文件(3KB)<END><br>10,findfiles.zip<br>使用递归算法在指定目录下查找文件(2KB)<END><br>11,listfiles.zip<br>在列表框中显示指定磁盘的所有文件, 文件名包含全路径名(10KB)<END><br>12,profile.zip<br>操作ini文件的例子(5KB)<br>13,scanfile.zip<br>如何在一个长文件中查找某一个特定的字符串(2KB)<END><br>14,iniedit.zip<br>如何编辑ini文件以及任何包含文本的windows文件(6KB)<END><br>15,helpfile.zip<br>在vb中调用help文件并实现winhelp的关键字、主题等功能(5KB)<END><br>16,split.zip<br>如何在vb中分割一个文件并组装恢复它(18KB)<END><br>17,fileinfo5.zip<br>演示了如何得到一个文件的信息,如文件属性、文件大小、文件的创建时间等等(11KB)<END><br>18,mfile.zip<br>打开多个文件的例子(33KB)<br>19,fileinfo1.zip<br>取得文件信息(4KB)<br>20,文件操作相关.zip<br>常用的4个文件函数:检查文件是否存在; 分离文件路径等(2KB)<br>21,winpe.zip<br>分析PE文件格式(105KB)<END><br>22,storage.zip <br>文件存储和流化的一些类(10KB)<END><br>23,reitp.zip <br>一个编写得十分专业的宽文本编辑器,功能比Windows中的写字板要好得多(90KB)<END><br>24,Exception.zip<br>文件异常处理的一个例子<2030kb><END><br>25,filefind.zip<br>在一个特定目录下查找文件的例子<1850kb><END><br>26,AddBook.zip<br>利用文件存盘的地址本管理小程序<2040kb><END><br>27,HexView.zip<br>读取文件内容并以二进制显示<2180kb><END>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值