关于如何阻止程序发生异常时弹出对话框的问题

  最近遇到一个棘手的问题,我们的产品在用户的实际环境下会弹出错误对话框,关掉对话框程序就退出了,后来调试发现是读取某些数据导致的,而读取这些数据是通过数据提供方提供的COM接口,不在我们的控制范围内,不去讨论。产品经理要求程序能够优雅的退出,加入retry机制。

  先搞定如何使程序优雅的退出,能找到数据的特征并优雅的绕过是最好的了,但这些数据从表面上来看和正常的数据并没什么两样,COM接口的实现我们也不清楚,只是通过调试发现崩溃的原因是调用wcscpy_s的时候,source参数为NULL了,通过C++的异常机制或者windows的__try无法捕捉到这个异常,不过找到了问题就应该好办。

  先百度,有人建议disable掉windows的error report,确实有用,不过这个方案经过讨论后被否定了,因为这个设置对其他的程序也有影响,被认为是不太友好的,enable error report的情况下也有过滤器,把程序加入到"Do not report errors for these programs"列表后,也没用,Dr. Watson还是会弹框...

  再谷歌,谷歌从未令人失望啊,Windows提供了个SetUnhandledExceptionFilter,看描述正是我想要的,而且似乎挺强大,赶紧试吧,编译运行......,我感觉这次应该没问题了吧,应该?事实证明我的感觉错了,我眉头一皱,菊花一紧,谷歌到了这篇文章,里面解释了为什么SetUnhandledExceptionFilter没起作用(有地方reset了),并提供了解决方案,但是被认为it is a scary approach。

  再谷歌,谷歌的威力确实不一样啊,发现C++ runtime提供了个_set_invalid_parameter_handler,看描述正是我真的想要的啊,而且更贴切,嘻嘻,果断加到了程序入口处,这次问题应该解决了吧,编译运行...,先去放个水,回来后程序应该优雅地结束了吧,哈哈... 1分钟后我哼着小曲回来正准备落座,那个熟悉的身影,没错,是它,而且我感觉它在笑,我和伙伴们都惊呆了,有点不可思议,为什么?RunTime的API还不够臭屁?难道和SetUnhandledExceptionFilter一样在某些地方被reset了吗?很容易验证,我在程序的多个地方调用_set_invalid_parameter_handler,返回值都一样,说明windows并没有reset,而且我在程序中故意用空指针作为wcscpy_s的参数调用它,没有弹框,再次证明调用_set_invalid_parameter_handler处理非法参数异常是有效的,难道仅仅是因为COM接口是第三方dll的原因吗?我照葫芦画瓢,也写了个dll,里面有wcscpy_s(dst, NULL),也有效啊...

  一定有更好的方法阻止这个讨厌的框跳出来,我甚至想在监控进程里面定时向这种错误对话框发wm_close消息,一出现就自动关掉,呵呵,也不是一个好的方案。我陷入了沉思,盯着程序崩溃时的call stack良久,正当我百思不得其解的时候,猛然注意到了MSVC runtime的版本号,COM dll依赖的是8.0,而我们的程序是在10.0下编译的,而_set_invalid_parameter_handler又是runtime提供的API,应该是和具体的runtime相关的,对,应该,这次我的感觉非常强烈,我感觉问题就在这里。经验证,等msvcr80.dll被加载了后,用GetProcAddress去获得_set_invalid_parameter_handler的地址再调用之,是有效的,那个框从此再也没有出现了,有人说在一个小岛上见到它,划着小船朝着太阳升起的地方,我默默地为它送上了祝福,眉头一展,菊花一松,后会有期!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值