Windows SEH发生crash,怎么回事?

Will. Liu 2020-12-17 10:20:11
我在Windows上写的一段代码:
__try {
foo_fun();
} __exception (EXCEPTION_EXECUTE_HANDLER) {
// write some log...
}

其中foo_fun()是一段可能会发生内存访问越界的代码。但是在我们测试同学的一台电脑上发现生成了崩溃dump,结果是崩溃在了foo_fun()中;
按我的理解SEH应该可以捕获所有软硬件的异常的,这就有一点奇怪了。不知道大家对这块儿了解不,欢迎讨论一下。
...全文
10994 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Will. Liu 2020-12-22
  • 打赏
  • 举报
回复
回复7楼: 是的,SEH能够“抓到”异常,但是不一定能够“处理”异常。一般来说,大部分异常是不可恢复的。 因为我知道这里可能出现的异常是什么,我这里也只是想要“抓到”异常。 问题在于,本来职责所在的“抓到”异常的环节,居然出现了crash现象。
an_bachelor 2020-12-22
  • 打赏
  • 举报
回复
引用 6 楼 Will. Liu 的回复:
foo_fun是一个系统API,按我之前对SEH的理解,不论foo_fun是什么代码,只要用__try __except包住,不应该会在__try中出现crash的。目前看起来好像这种不可能的事情发生了。
这是msdn的原文(https://docs.microsoft.com/en-us/windows/win32/debug/exception-handling): An exception can be continuable or noncontinuable. A noncontinuable exception arises when the event is not continuable in the hardware, or if continuation makes no sense. A noncontinuable exception does not terminate the application. Therefore, an application may be able to catch the exception and run. However, a noncontinuable exception typically arises as a result of a corrupted stack or other serious problem, making it difficult to recover from the exception. 我英语不好 翻看了一些英文语法资料“an application may be able to catch the exception and run” 还是不能完全肯定是“有可能可以捕获非可继续的异常”还是“可以有办法捕获非可继续的异常”,看起来大家一般的用法是前者(may be able to - 可能可以),但这个文档前面说“不可继续的异常不会中断程序,因此”好像又应该是后者? 不过最后一句话明确说“通常导致对战破坏或别的问题,让你很难从异常中恢复”,那么出现这种状况的时候,你能不能捕获大概也没区别了?因为重要的堆栈或其他有用的数据也可能已经被毁坏。
Will. Liu 2020-12-22
  • 打赏
  • 举报
回复
foo_fun是一个系统API,按我之前对SEH的理解,不论foo_fun是什么代码,只要用__try __except包住,不应该会在__try中出现crash的。目前看起来好像这种不可能的事情发生了。
zgl7903 2020-12-21
  • 打赏
  • 举报
回复
那要看 foo_fun 中怎么处理的, 如果函数中也有 _try _except 捕捉异常,异常不一定传递给到上一级 生成的 dump 一般可以复制到 原始编译生成目录下, 用VS打开F5调试的, 如果生成时有.pdb 调试符号文件,可以看到奔溃处及调用堆栈,很容易追踪到问题 或者可以在容易奔溃的机器上安装远程调试器, 打开VS 调试菜单下的所以异常, 远程调试下
luj_1768 2020-12-21
  • 打赏
  • 举报
回复
测试同学的那台电脑配置是否比较低端?你使用的是系统底层调试例程,如果响应超时有可能造成系统崩溃。这种例程应该是非常可靠的。
Will. Liu 2020-12-21
  • 打赏
  • 举报
回复
我看了一下,测试的那台电脑性能应该不算太低: 0:094> !cpuid CP F/M/S Manufacturer MHz 0 6,78,3 GenuineIntel 2300 1 6,78,3 GenuineIntel 2300 2 6,78,3 GenuineIntel 2300 3 6,78,3 GenuineIntel 2300
Will. Liu 2020-12-18
  • 打赏
  • 举报
回复
不是的,这个意思是说__try里面的内容当作已知异常处理。
aabbabababaa 2020-12-18
  • 打赏
  • 举报
回复
__exception (EXCEPTION_EXECUTE_HANDLER)
只捕获这种异常吧?
在过去几年里,崩溃转储(crash dump)成为了调试工作的一个重要部分。如果软件在客户现场或者测试实验室发生故障,最有价值的解决方式是能够创建一个故障瞬间的应用程序状态镜像,然后可以在开发者的机器上通过调试器进行分析。第一代的crash dump通常被称为“全用户转储(full user dump)”,它包含了进程的虚拟内存的全部内容。毫无疑问,这样的dump对于事后调试非常有价值。但是,这样的dump经常非常大,使得通过电子方式发送给开发者非常困难,甚至没法完成。另外,没用公共接口可以通过程序调用来创建dump,我们必须依赖于第三方工具(例如,Dr. Watson 或者Userdump)来创建他们。 随着Windows XP,微软发布了一组新的被称为“minidump”的崩溃转存技术。Minidump很容易定制。按照最常用的配置,一个minidump只包括了最必要的信息,用于恢复故障进程的所有线程的调用堆栈,以及查看故障时刻局部变量的值。这样的dump文件通常很小(只有几K字节)。所以,很容易通过电子方式发送给软件开发人员。一旦需要,minidump甚至可以包含比原来的crash dump更多的信息。例如,可以包含进程使用的内核对象的信息。另外,DbgHelp.dll提供了通过编程创建minidump的公开API。而且,它是可以重新发布的。我们可以不再依赖于外部工具。 minidump可以定制,给我们带来了一个问题-保存多少应用程序状态信息才能既保证调试有效,又能够尽量保证minidump文件尽可能小?尽管调试简单的异常访问只需要调用堆栈和局部变量的信息,但是解决更复杂的问题需要更多的信息。例如,我们可能需要查看全局变量的值、检查堆的完整性和分析进程虚拟内存的布局。同时,可执行程序的代码段往往是多余的,开发用的机器上可以很容易找到这些执行程序。 幸运的是我们可以通过DbgHelp函数组(MiniDumpWriteDump和MiniDumpCallback)来控制这些功能,甚至可以更复杂。在这篇文章里面,我们会解释怎么样使用这些函数来创建mindump,保证文件足够小但是又能有效调试。也会讲解minidump中应该包括那些数据,并且如何使用通用调试器(WinDbg和VS.NET)来看这些信息。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧