【问题标题】:Is it safe to catch EXCEPTION_GUARD_PAGE捕获 EXCEPTION_GUARD_PAGE 是否安全
【发布时间】:2011-03-04 18:21:36
【问题描述】:

在各种 Win 平台(XP 及更高版本)上环境为 VC++ 9

我正在编写一个未处理的异常处理程序。我在内核时代有一个模糊的回忆,即捕获 EXCEPTION_GUARD_PAGE 是不好的,因为它是为了告诉操作系统扩大堆栈而生成的。

我的问题有两个:

  1. 用户空间会不会出现这样的异常?

  2. 如果可以,抓到它安全吗?

我对用它做任何事情都不是特别感兴趣。我只是想知道是否需要将特殊代码放入捕获它(因为我现在正在捕获所有内容)。

__更新:__

我记得我的来源,是Raymond Chen的博客(http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx

我最初担心的是,在捕获所有异常时,如果我捕获了 EXCEPTION_GUARD_PAGE,我可能会阻止操作系统看到异常并扩大堆栈。

进一步考虑,我怀疑 EXCEPTION_GUARD_PAGE 可能在生成它的读/写操作期间在内核中处理,因此永远不会到达我的用户空间代码。

我想我正在寻找某人来证实(或反驳)这一点。

__第二次更新:__

我还没有选择答案,因为没有人真正回答过这个问题。我会保持打开状态,希望有人可以提供我所寻求的信息。

__第三次更新__

仍然生活在(微弱的)希望中。

__第四次更新__

嗯,我从来没有得到一个有用的答案。当我问这个问题时,我早就完成了我正在编写的模块。我认为,出于实际目的,这个问题已经死了。我可能不会再更新了。

【问题讨论】:

  • Windows 不会自动扩大堆栈。
  • 克里斯托弗——是的。阅读我链接到的 Raymond Chen 的文章。

标签: c++ exception winapi


【解决方案1】:

使用 VirtualProtectEx() 设置页面以生成 STATUS_GUARD_PAGE_VIOLATION,并且 PAGE_GUARD 标志是 documented procedure。一个页面只能生成一次异常,因此在处理异常时不会有死亡的危险。

我没有为异常做任何特别的事情,但这并不能证明太多,得到这个异常是非常罕见的。在我们的任何崩溃报告中都从未见过它。

该功能实际上是用于生成堆栈溢出异常。你真的需要特别处理,因为你剩下的筹码太少了。我认为这就是您在问题中提到的警告的来源。但是,它永远不会生成页面保护异常,该异常在转换为堆栈溢出之前在内核级别进行处理。

【讨论】:

  • 实际上在内核模式下你需要处理它。你让它通过操作系统,它扩大了堆栈。如果你抓住它,操作系统就看不到它,并且堆栈永远不会扩大并且会发生堆栈溢出。我的问题是它是否可以在用户模式下生成。我的猜测是“不”,但我正在寻找确认。
  • 问并回答:“但是它永远不会生成页面保护异常,这是在内核级别处理的”。
【解决方案2】:

根据我对 virtualquery 的观察,它类似于内核模式的情况。如果访问的保护页堆栈不属于访问线程,则调试器可以捕获该异常。无论如何,你应该已经有了答案。

【讨论】:

  • 你能再解释一下吗?我不太清楚你的意思。您可能可以弄清楚特定页面是否具有“保护页面”属性,但是如何使用 VirtualQuery() 检测其异常行为?我没有看到在用户模式下抛出 EXCEPTION_GUARD_PAGE 异常,但我可能没有成功耗尽堆栈内存来触发一个。
【解决方案3】:

根据MSDN

线程访问分配的内存 使用 PAGE_GUARD 修饰符。

这听起来像是不应该发生的事情,除非你有错误;所以我会相应地处理它。

编辑

操作系统异常处理程序在您之前注册,因此您自己处理它并不意味着操作系统没有先看到它。

【讨论】:

  • 堆栈中的最后一页具有 GUARD PAGE 属性。当您访问它时,它会生成一个异常来警告操作系统扩大堆栈。至少,这是在内核模式下发生的。不确定它在用户空间中是如何工作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多