VS2005中SetUnhandledExceptionFilter函数应用

很多软件通过设置自己的异常捕获函数,捕获未处理的异常,生成报告或者日志(例如生成mini-dump文件),达到Release版本下追踪Bug的目的。但是,到了VS2005(即VC8),Microsoft对CRT(C运行时库)的一些与安全相关的代码做了些改动,典型的,例如增加了对缓冲溢出的检查。新CRT版本在出现错误时强制把异常抛给默认的调试器(如果没有配置的话,默认是Dr.Watson),而不再通知应用程序设置的异常捕获函数,这种行为主要在以下三种情况出现。

(1)       调用abort函数,并且设置了_CALL_REPORTFAULT选项(这个选项在Release版本是默认设置的)。

(2)       启用了运行时安全检查选项,并且在软件运行时检查出安全性错误,例如出现缓存溢出。(安全检查选项/GS 默认也是打开的)

(3)       遇到_invalid_parameter错误,而应用程序又没有主动调用

_set_invalid_parameter_handler设置错误捕获函数。

所以结论是,使用VS2005(VC8)编译的程序,许多错误都不能在SetUnhandledExceptionFilter捕获到。这是CRT相对于前面版本的一个比较大的改变,但是很遗憾,Microsoft却没有在相应的文档明确指出。

解决方法

       之所以应用程序捕获不到那些异常,原因是因为新版本的CRT实现在异常处理中强制删除所有应用程序先前设置的捕获函数,如下所示:

 /* Make sure any filter already in place is deleted. */

 SetUnhandledExceptionFilter(NULL);

 UnhandledExceptionFilter(&ExceptionPointers);

解决方法是拦截CRT调用SetUnhandledExceptionFilter函数,使之无效。在X86平台下,可以使用以下代码。

#ifndef _M_IX86

       #error "The following code only works for x86!"

#endif

 

void DisableSetUnhandledExceptionFilter()

{

    void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")),

                                                         "SetUnhandledExceptionFilter");

    if (addr)

    {

              unsigned char code[16];

              int size = 0;

              code[size++] = 0x33;

              code[size++] = 0xC0;

              code[size++] = 0xC2;

              code[size++] = 0x04;

              code[size++] = 0x00;

 

               DWORD dwOldFlag, dwTempFlag;

              VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);

              WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);

              VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);

       }

}

在设置自己的异常处理函数后,调用DisableSetUnhandledExceptionFilter禁止CRT设置即可。

其它讨论

       上面通过设置api hook,解决了在VS2005上的异常捕获问题,这种虽然不是那么“干净”的解决方案,确是目前唯一简单有效的方式。

       虽然也可以通过_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT), signal(SIGABRT, ...),和_set_invalid_parameter_handler(...) 解决(1)(3),但是对于(2),设置api hook是唯一的方式。

时间: 2024-09-20 04:16:36

VS2005中SetUnhandledExceptionFilter函数应用的相关文章

排除vs2005中的不安全函数警告

下面的代码: #include <stdio.h> #include <minmax.h> int main( ) { int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("max=%d",c); return 0; } 使用vs2005编译时会遇到这样一个warning: warning C4996: 'scanf' was declared deprecated 其实 w

python中enumerate函数用法实例分析

  本文实例讲述了python中enumerate函数用法.分享给大家供大家参考.具体分析如下: 今日发现一个新函数 enumerate .一般情况下对一个列表或数组既要遍历索引又要遍历元素时,会这样写: ? 1 2 for i in range (0,len(list)): print i ,list[i] 但是这种方法有些累赘,使用内置enumerrate函数会有更加直接,优美的做法,先看看enumerate的定义: ? 1 2 3 4 5 6 7 def enumerate(collect

位图显示-MFC中OnPaint函数显示BMP图片的问题

问题描述 MFC中OnPaint函数显示BMP图片的问题 为什么我在MFC对话框中,在OnPaint函数中加入以下代码,BMP图像不能显示啊~~· BITMAP bm; CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); CDC memdc; CDC dc; memdc.CreateCompatibleDC(&dc);/ bmp.GetBitmap(&bm); CBitmap *bmpold=memdc.SelectObject(&bmp);/ dc

Excel中sumif函数的怎么使用

  Excel中sumif函数的使用方法 Excel中sumif函数的用法是根据指定条件对若干单元格.区域或引用求和. SUMIF函数的参数:range,criteria,sum_range 1)Range为条件区域,用于条件判断的单元格区域. 2)Criteria是求和条件,由数字.逻辑表达式等组成的判定条件.为确定哪些单元格将被相加求和的条件,其形式可以为数字.表达式或文 本.例如,条件可以表示为 32."32".">32" 或 "apples&

Excel中sumif函数用法

今天接着给大家来关于Excel中sumif函数用法的操作技巧,那么就有人问了,学会了Excel中sumif函数用法有什么作用呢,不要急,下面就请听小编一一给大家进行详细的讲解: 一.SUMIF函数介绍 SUMIF函数根据指定条件对若干单元格求和,该条件可以是数值.文本或表达式,可以应用在人事.工资和成绩统计中. 二.SUMIF函数用法 sumif函数语法是:SUMIF(range,criteria,sum_range) 第一个参数:Range为条件区域,用于条件判断的单元格区域. 第二个参数:C

画图-如何用MFC中OnDraw函数输出的文字是反向的?

问题描述 如何用MFC中OnDraw函数输出的文字是反向的? 如题,要用绘图程序画图,在OnDraw函数中,如何输出反向的文字? 解决方案 自己先把文字反向reverse了,再OnDraw来TextOut 解决方案二: 只能是先把你要输出的字符改为反向的,然后再输出,比如用strrev来吧字符串反向一下

link中是不是只能调用sqlfunctions中的函数?能不能给sqlfunctions增加函数?

问题描述 link中是不是只能调用sqlfunctions中的函数?能不能给sqlfunctions增加函数? link中是不是只能调用sqlfunctions中的函数?能不能给sqlfunctions增加函数? 解决方案 可以调用自定义函数,不过前提是函数要在sql里面实现 参考:http://www.cnblogs.com/lyj/archive/2008/03/19/1112356.html 否则只能先用AsEnumerable转换成Linq to Objects,再执行.

js中回调函数问题,程序进不了回调函数

问题描述 js中回调函数问题,程序进不了回调函数 我这段代码的回调函数哪出错,请各位大神指教 function req(){ createRequest(); var zipcode=document.getElementById(""zipcode"").value; var url=""b.jsp?zipcode="" + escape(zipcode); request.open(""POST&quo

AJAX入门之深入理解&amp;#106avascript中的函数

ajax|函数 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解.javascript中的函数不同于其他的语言,每个函数都是作为一个对象被维护和运行的.通过函数对象的性质,可以很方便的将一个函数赋值给一个变量或者将函数作为参数传递.在继续讲述之前,先看一下函数的使用语法: function func1(-){-}var func2=function(-){-};var func3=function func4(-){-};var func5=new Funct