通过C++的try和catch来捕获SEH异常
在初学VC的时候,总以为try()catch(...)可以抓到所有的异常. 在开发之前开发的一个服务器程序中,才发现服务器经常莫名其妙的宕机了.一直觉得很诡异.
直到后来看了很多资料才明白结构化异常跟C++异常是两套东西,不统一。有些异常try.catch不一定能不抓到. 要将两种异常共同使用.下面的代码可以达到目的. 使用下面异常类,可以使程序更稳定.(注意:编译选项里面要记得打开 结构化异常开关. compile with: /EHa)
- // 把结构化异常转化为C++异常
- struct SException
- {
- EXCEPTION_RECORD er;
- CONTEXT context;
- SException(PEXCEPTION_POINTERS pep)
- {
- er = *(pep->ExceptionRecord);
- context = *(pep->ContextRecord);
- }
- operator DWORD() { return er.ExceptionCode; }
- static void MapSEtoCE() { _set_se_translator( TranslateSEToCE ); }
- static void __cdecl TranslateSEToCE( UINT dwEC, PEXCEPTION_POINTERS pep )
- {
- throw SException(pep);
- }
- };
- void main()
- {
- SException::MapSEtoCE();
- try
- {
- int* p = 0;
- int a = *p;
- }
- catch( SException& e )
- {
- if ( (DWORD)e == EXCEPTION_ACCESS_VIOLATION )
- {
- printf( "Access violation" );
- }
- }
- }
另外可以调用MS提供的函数SetUnhandledExceptionFilter, 这是程序异常未处理的最后一到防线.可以在回调函数中写出DUMP文件,然后通过PDB文件来调试看到宕机的源代码段.
- LONG __stdcall MyCrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
- {
- #ifdef _M_IX86
- if (pEx->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
- {
- // be sure that we have enought space...
- static char MyStack[1024*128];
- // it assumes that DS and SS are the same!!! (this is the case for Win32)
- // change the stack only if the selectors are the same (this is the case for Win32)
- //__asm push offset MyStack[1024*128];
- //__asm pop esp;
- __asm mov eax,offset MyStack[1024*128];
- __asm mov esp,eax;
- }
- #endif
- bool bFailed = true;
- HANDLE hFile;
- hFile = CreateFile(szMiniDumpFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- MINIDUMP_EXCEPTION_INFORMATION stMDEI;
- stMDEI.ThreadId = GetCurrentThreadId();
- stMDEI.ExceptionPointers = pEx;
- stMDEI.ClientPointers = TRUE;
- // try to create an miniDump:
- if (s_pMDWD(
- GetCurrentProcess(),
- GetCurrentProcessId(),
- hFile,
- MiniDumpNormal,
- &stMDEI,
- NULL,
- NULL
- ))
- {
- bFailed = false; // suceeded
- }
- CloseHandle(hFile);
- }
- if (bFailed)
- {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- if (bMsgbox)
- {
- string strMsg = "Run failed, Please Copy the ";
- strMsg += szMiniDumpFileName;
- strMsg += " file to us!";
- ::MessageBox(NULL, strMsg.c_str(), TEXT("Error"), 0);
- }
- // or return one of the following:
- // - EXCEPTION_CONTINUE_SEARCH
- // - EXCEPTION_CONTINUE_EXECUTION
- // - EXCEPTION_EXECUTE_HANDLER
- return EXCEPTION_EXECUTE_HANDLER; // this will trigger the "normal" OS error-dialog
- }
- #ifndef _M_IX86
- #error "The following code only works for x86!"
- #endif
- LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
- LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
- {
- return NULL;
- }
- BOOL PreventSetUnhandledExceptionFilter()
- {
- HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
- if (hKernel32 == NULL) return FALSE;
- void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
- if(pOrgEntry == NULL) return FALSE;
- unsigned char newJump[ 100 ];
- DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
- dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
- void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
- DWORD dwNewEntryAddr = (DWORD) pNewFunc;
- DWORD dwRelativeAddr = dwNewEntryAddr-dwOrgEntryAddr;
- newJump[ 0 ] = 0xE9; // JMP absolute
- memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc));
- SIZE_T bytesWritten;
- BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
- pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
- return bRet;
- }
- void InitMiniDumpWriter()
- {
- if (s_hDbgHelpMod != NULL)
- return;
- // Initialize the member, so we do not load the dll after the exception has occured
- // which might be not possible anymore...
- s_hDbgHelpMod = LoadLibrary(_T("dbghelp.dll"));
- if (s_hDbgHelpMod != NULL)
- s_pMDWD = (tMDWD) GetProcAddress(s_hDbgHelpMod, "MiniDumpWriteDump");
- // Register Unhandled Exception-Filter:
- LPTOP_LEVEL_EXCEPTION_FILTER p = SetUnhandledExceptionFilter(MyCrashHandlerExceptionFilter);
- BOOL bRet = PreventSetUnhandledExceptionFilter();
- // Additional call "PreventSetUnhandledExceptionFilter"...
- // See also: "SetUnhandledExceptionFilter" and VC8 (and later)
- // http://blog.kalmbachnet.de/?postid=75
- }
通过C++的try和catch来捕获SEH异常相关推荐
- 关于如何使用c++中的try/catch捕获SEH异常并处理
两者区别: C++异常与SEH区别可参考<Windows核心编程第五版>第25章 25.2节(727页) 下面取自原文: 注意: C++异常和SEH异常不是同一个东西!!! C++使用tr ...
- java try catch嵌套_解析Java中未被捕获的异常以及try语句的嵌套使用
Java未被捕获的异常 在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的.下面的小程序包括一个故意导致被零除错误的表达式. class Exc0 { public st ...
- WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常。即使你捕获了异常,仍有可能一直保持连接。...
WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常.即使你捕获了异常,仍有可能一直保持连接.让我们来看看形成这一问题的历史原因,并提出几个补救措施. 在.NET中,资源管理的基础就 ...
- winform程序捕获全局异常,对错误信息写入日志并弹窗
使用场景:在winform程序中如果没对方法进行try catch操作,若方法内出错,则整个程序报错并退出,如下图 如果程序已在客户手中,若没对错误的详细信息进行拍照,我们则不知道错误原因是什么.我们 ...
- C# winform 捕获全局异常
using System; using System.Collections.Generic; using System.Windows.Forms; using System.IO; namespa ...
- Android application捕获崩溃异常
Java代码 个人笔记: 通用 application 1.收集所有 avtivity 用于彻底退出应用 2.捕获崩溃异常,保存错误日志,并重启应用 public class HKBaseApplic ...
- 加了try的情况下线程中抛出未捕获的异常
一.问题描述 项目中线程中明明加了try catch 捕获异常,但是一启动就报未捕获的异常导致整个程序崩溃. 下面是windows中的错误日志. Application: 岗亭收费.exe Frame ...
- 10.6 捕获处理异常
异常处理:方式一:捕获处理捕获处理的格式:try{可能发生异常的代码}catch(捕获的异常类型 变量名){处理异常的代码}方式二:抛出处理 public class CaptureException ...
- Java多线程:捕获线程异常
你处理过多线程中的异常吗?如何捕获多线程中发生的异常?捕获子线程的异常与捕获当前线程的异常一样简单吗? 除了try catch.Java中还可以通过异常处理器UncaughtExceptionHand ...
最新文章
- 异步发送邮件、短信、微信
- 黑盒测试 白盒测试 题
- java Interface
- status debug when entering opportunity overview page
- 翻译的一篇关于学习编程语言的小文章
- android studio aspectj使用,androidStudio中使用 AspectJ
- Linux学习笔记---移植官方linux步骤(二)
- java设计模式之组合模式
- linux vim命令的意思,Linux 中 vim 是什么意思?
- 黑苹果alc269声卡仿冒id_黑苹果定制声卡驱动(ALC892为例)
- mysql获取表属性和表结构
- opencv------绘制文本
- IDEA配置文件乱码
- 论文笔记 Multiple Instance Detection Network with Online Instance Classifier Refinement - CVPR 2017
- 雷达原理-雷达发射机
- 233网校计算机二级百度云盘6,2014年计算机二级考试《 Access》机考操作题题库(6)...
- 皮一皮:听说有个东西叫充气娃娃...
- MATLAB 求解最优化问题
- 基于RT-Thread+RA6M4的智能安防系统
- 云原生的C语言代码?