在初学VC的时候,总以为try()catch(...)可以抓到所有的异常. 在开发之前开发的一个服务器程序中,才发现服务器经常莫名其妙的宕机了.一直觉得很诡异.

直到后来看了很多资料才明白结构化异常跟C++异常是两套东西,不统一。有些异常try.catch不一定能不抓到. 要将两种异常共同使用.下面的代码可以达到目的. 使用下面异常类,可以使程序更稳定.(注意:编译选项里面要记得打开 结构化异常开关. compile with: /EHa)

[cpp] view plaincopy
  1. // 把结构化异常转化为C++异常
  2. struct SException
  3. {
  4. EXCEPTION_RECORD er;
  5. CONTEXT            context;
  6. SException(PEXCEPTION_POINTERS pep)
  7. {
  8. er       = *(pep->ExceptionRecord);
  9. context = *(pep->ContextRecord);
  10. }
  11. operator DWORD() { return er.ExceptionCode; }
  12. static void MapSEtoCE() { _set_se_translator( TranslateSEToCE ); }
  13. static void __cdecl TranslateSEToCE( UINT dwEC, PEXCEPTION_POINTERS pep )
  14. {
  15. throw SException(pep);
  16. }
  17. };
  18. void main()
  19. {
  20. SException::MapSEtoCE();
  21. try
  22. {
  23. int* p = 0;
  24. int a = *p;
  25. }
  26. catch( SException& e )
  27. {
  28. if ( (DWORD)e == EXCEPTION_ACCESS_VIOLATION )
  29. {
  30. printf( "Access violation" );
  31. }
  32. }
  33. }

另外可以调用MS提供的函数SetUnhandledExceptionFilter, 这是程序异常未处理的最后一到防线.可以在回调函数中写出DUMP文件,然后通过PDB文件来调试看到宕机的源代码段.

[cpp] view plaincopy
  1. LONG __stdcall MyCrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
  2. {
  3. #ifdef _M_IX86
  4. if (pEx->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
  5. {
  6. // be sure that we have enought space...
  7. static char MyStack[1024*128];
  8. // it assumes that DS and SS are the same!!! (this is the case for Win32)
  9. // change the stack only if the selectors are the same (this is the case for Win32)
  10. //__asm push offset MyStack[1024*128];
  11. //__asm pop esp;
  12. __asm mov eax,offset MyStack[1024*128];
  13. __asm mov esp,eax;
  14. }
  15. #endif
  16. bool bFailed = true;
  17. HANDLE hFile;
  18. hFile = CreateFile(szMiniDumpFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  19. if (hFile != INVALID_HANDLE_VALUE)
  20. {
  21. MINIDUMP_EXCEPTION_INFORMATION stMDEI;
  22. stMDEI.ThreadId = GetCurrentThreadId();
  23. stMDEI.ExceptionPointers = pEx;
  24. stMDEI.ClientPointers = TRUE;
  25. // try to create an miniDump:
  26. if (s_pMDWD(
  27. GetCurrentProcess(),
  28. GetCurrentProcessId(),
  29. hFile,
  30. MiniDumpNormal,
  31. &stMDEI,
  32. NULL,
  33. NULL
  34. ))
  35. {
  36. bFailed = false;  // suceeded
  37. }
  38. CloseHandle(hFile);
  39. }
  40. if (bFailed)
  41. {
  42. return EXCEPTION_CONTINUE_SEARCH;
  43. }
  44. if (bMsgbox)
  45. {
  46. string strMsg = "Run failed, Please Copy the ";
  47. strMsg += szMiniDumpFileName;
  48. strMsg += " file to us!";
  49. ::MessageBox(NULL, strMsg.c_str(), TEXT("Error"), 0);
  50. }
  51. // or return one of the following:
  52. // - EXCEPTION_CONTINUE_SEARCH
  53. // - EXCEPTION_CONTINUE_EXECUTION
  54. // - EXCEPTION_EXECUTE_HANDLER
  55. return EXCEPTION_EXECUTE_HANDLER;  // this will trigger the "normal" OS error-dialog
  56. }
  57. #ifndef _M_IX86
  58. #error "The following code only works for x86!"
  59. #endif
  60. LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
  61. LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
  62. {
  63. return NULL;
  64. }
  65. BOOL PreventSetUnhandledExceptionFilter()
  66. {
  67. HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  68. if (hKernel32 == NULL) return FALSE;
  69. void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
  70. if(pOrgEntry == NULL) return FALSE;
  71. unsigned char newJump[ 100 ];
  72. DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
  73. dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
  74. void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
  75. DWORD dwNewEntryAddr = (DWORD) pNewFunc;
  76. DWORD dwRelativeAddr = dwNewEntryAddr-dwOrgEntryAddr;
  77. newJump[ 0 ] = 0xE9;  // JMP absolute
  78. memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc));
  79. SIZE_T bytesWritten;
  80. BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
  81. pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
  82. return bRet;
  83. }
  84. void InitMiniDumpWriter()
  85. {
  86. if (s_hDbgHelpMod != NULL)
  87. return;
  88. // Initialize the member, so we do not load the dll after the exception has occured
  89. // which might be not possible anymore...
  90. s_hDbgHelpMod = LoadLibrary(_T("dbghelp.dll"));
  91. if (s_hDbgHelpMod != NULL)
  92. s_pMDWD = (tMDWD) GetProcAddress(s_hDbgHelpMod, "MiniDumpWriteDump");
  93. // Register Unhandled Exception-Filter:
  94. LPTOP_LEVEL_EXCEPTION_FILTER p = SetUnhandledExceptionFilter(MyCrashHandlerExceptionFilter);
  95. BOOL bRet = PreventSetUnhandledExceptionFilter();
  96. // Additional call "PreventSetUnhandledExceptionFilter"...
  97. // See also: "SetUnhandledExceptionFilter" and VC8 (and later)
  98. // http://blog.kalmbachnet.de/?postid=75
  99. }

通过C++的try和catch来捕获SEH异常相关推荐

  1. 关于如何使用c++中的try/catch捕获SEH异常并处理

    两者区别: C++异常与SEH区别可参考<Windows核心编程第五版>第25章 25.2节(727页) 下面取自原文: 注意: C++异常和SEH异常不是同一个东西!!! C++使用tr ...

  2. java try catch嵌套_解析Java中未被捕获的异常以及try语句的嵌套使用

    Java未被捕获的异常 在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的.下面的小程序包括一个故意导致被零除错误的表达式. class Exc0 { public st ...

  3. WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常。即使你捕获了异常,仍有可能一直保持连接。...

    WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常.即使你捕获了异常,仍有可能一直保持连接.让我们来看看形成这一问题的历史原因,并提出几个补救措施. 在.NET中,资源管理的基础就 ...

  4. winform程序捕获全局异常,对错误信息写入日志并弹窗

    使用场景:在winform程序中如果没对方法进行try catch操作,若方法内出错,则整个程序报错并退出,如下图 如果程序已在客户手中,若没对错误的详细信息进行拍照,我们则不知道错误原因是什么.我们 ...

  5. C# winform 捕获全局异常

    using System; using System.Collections.Generic; using System.Windows.Forms; using System.IO; namespa ...

  6. Android application捕获崩溃异常

    Java代码 个人笔记: 通用 application 1.收集所有 avtivity 用于彻底退出应用 2.捕获崩溃异常,保存错误日志,并重启应用 public class HKBaseApplic ...

  7. 加了try的情况下线程中抛出未捕获的异常

    一.问题描述 项目中线程中明明加了try catch 捕获异常,但是一启动就报未捕获的异常导致整个程序崩溃. 下面是windows中的错误日志. Application: 岗亭收费.exe Frame ...

  8. 10.6 捕获处理异常

    异常处理:方式一:捕获处理捕获处理的格式:try{可能发生异常的代码}catch(捕获的异常类型 变量名){处理异常的代码}方式二:抛出处理 public class CaptureException ...

  9. Java多线程:捕获线程异常

    你处理过多线程中的异常吗?如何捕获多线程中发生的异常?捕获子线程的异常与捕获当前线程的异常一样简单吗? 除了try catch.Java中还可以通过异常处理器UncaughtExceptionHand ...

最新文章

  1. 异步发送邮件、短信、微信
  2. 黑盒测试 白盒测试 题
  3. java Interface
  4. status debug when entering opportunity overview page
  5. 翻译的一篇关于学习编程语言的小文章
  6. android studio aspectj使用,androidStudio中使用 AspectJ
  7. Linux学习笔记---移植官方linux步骤(二)
  8. java设计模式之组合模式
  9. linux vim命令的意思,Linux 中 vim 是什么意思?
  10. 黑苹果alc269声卡仿冒id_黑苹果定制声卡驱动(ALC892为例)
  11. mysql获取表属性和表结构
  12. opencv------绘制文本
  13. IDEA配置文件乱码
  14. 论文笔记 Multiple Instance Detection Network with Online Instance Classifier Refinement - CVPR 2017
  15. 雷达原理-雷达发射机
  16. 233网校计算机二级百度云盘6,2014年计算机二级考试《 Access》机考操作题题库(6)...
  17. 皮一皮:听说有个东西叫充气娃娃...
  18. MATLAB 求解最优化问题
  19. 基于RT-Thread+RA6M4的智能安防系统
  20. 云原生的C语言代码?

热门文章

  1. 关于js的引用类型和基本类型
  2. MyISAM的key_buffer_size和InnoDB的innodb_buffer_pool_size
  3. 理解纯CSS画三角形
  4. 仿QQ锁屏界面消息提示
  5. Adsutil.vbs 在脚本攻击中的妙用
  6. 基于TCP的Socket网络编程,有图有代码
  7. 数字证书注册审批机构(RA)
  8. 微信小程序 开发文档
  9. CVS/SVN/GIT
  10. 3110: [Zjoi2013]K大数查询