我出乎意料地生成结构化异常。我应该使用__try / __除()吗?

时间:2013-02-05 03:03:28

标签: debugging visual-c++

我有一个神秘的崩溃,我正在努力找到在MSVC 2005中编译的大型多线程应用程序。该应用程序在客户端日常使用,任何崩溃都会对它们造成严重破坏。我需要一个解决方法。如果我可以将问题隔离到一个函数,并按照这些方式做一些事情:

__try
{
  FunctionWhichMayCauseCrash();
}
__except ( [filter expression] )
{
  Recover();  // magic - this allows us to prevent crash and continue
}
那么这在理论上对我来说似乎是一个好主意。在实践中,有些人(例如拉里奥斯特曼here和道格哈里森here)听起来似乎是一个非常糟糕的主意 - 不应该用驳船杆触及SEH。

现实检查:我的程序正在生成结构化异常,我不知道在哪里。我正在使用Hans Dietrich's XCrashReport的部分内容 - 它本身使用__try/__except - 试图深入了解这些异常的来源,但到目前为止还没有运气。似乎某些共享资源没有被正确锁定,因此一个线程正在从另一个线程下面拉出地毯,导致在一个或多或少的随机位置发生访问冲突。

是否有一个务实的中间立场,这样的机制可以阻止我的程序崩溃?我是否应该担心我选择的崩溃恢复机制会使用别人担心的东西?

澄清:由于程序崩溃导致的极端中断,我寻求一种可以防止崩溃的解决方法,而不是最终的永久性解决方案。我无意使用__try/__except来解决问题。我只是想了解它是否像有些人听起来一样危险,或者是一个应该谨慎使用的合法工具。有些人说话的方式,就在我尝试用/EHa定义编译我的代码的那一刻,我的电脑可能会迸发出火焰。我很想知道人们是否会说使用/EHa_set_se_translatortry/catch(...)更好,或者说是相同的事情,或者两者是否都是错误的想法。

澄清2:我不需要帮助调试:-)相反,我需要帮助理解混合SEH和C ++的含义,这似乎产生的热量比光和其它光更多论坛。我的低声誉表明论坛的新颖性,而不是C ++的新颖性。我故意将我的应用程序抽象出来,以鼓励人们关注将SEH结构引入C ++程序的含义。好吧,这不起作用:-)碰巧,我的应用程序有一个对象管道,如果我检测到它们中的腐败,我可以轻易转储。因此,我的神奇Recover()功能并不像它听起来那么神奇,并且腐败很可能仅限于堆的一小部分。所以...回到问题:使用__try/__except是否合适?

2 个答案:

答案 0 :(得分:1)

<强>执行。不。做。此

我完全同意Doug Harrison对你链接的评论 - 使用SEH是非常危险的,因为你最终在你的代码中隐藏(可能是严重的)错误。

如果您对可能发生异常的位置有一个非常具体的想法,那么在您的代码中临时添加SEH块可能有助于跟踪它,但我怀疑情况并非如此 - 您的堆栈已损坏。

我建议不要在程序的很大一部分中添加SEH块,因为它所做的就是以避免隐藏这些问题为代价来防止程序崩溃。您将隐藏崩溃,但您不知道您的应用程序的状态是否已损坏(以及在何种程度上)。如果损坏的数据保存在数据库中,您的客户将无法获得太多帮助。

这是另一个SEH question,我认为它对您有用。

不要试图使用SEH,而是要花时间和精力来解决问题。使用WinDbg(如果你有崩溃的minidump)可以加快速度。如果你不熟悉它,这里是tutorial

我不是SEH专家,所以其他人可能会给你更详细的建议,但我只会尝试SEH解决方案作为一个非常非常的最后手段,因为可能更难找到问题。

答案 1 :(得分:0)

问题在于,在调用SEH时,您的应用程序已完全被清除。 任何可以访问(不仅仅被FunctionWhichMayCauseCrash使用的)的RAM必须被假定为销毁,包括CRT在用户空间中完成的所有操作。真正做的最好的事情就是记录你可以得到的所有东西 - 以一种完全取决于内核功能的方式 - 中止整个过程,关闭所有的IPC和共享句柄,并在它自己开始一个闪亮的新过程地址空间。

如果您真的希望在这种情况下进行细粒度的崩溃恢复,您可能需要重新构建一系列管道连接流程或其他流程。