在非C ++异常的情况下解锁关键部分

时间:2009-04-29 14:31:21

标签: c++ multithreading exception mfc

我的类中有一个CCriticalSection对象,用于将异常同步到方法。我将它与CSingleLock对象一起使用,如下所示:

void f()
{
  try
   {
     CSingleLock lock(&m_synchronizer, TRUE);
     .....
     .....

   }

  catch(SomeException )
  {
  }

  catch(...)
  {
  }

}

如果任何语句抛出C ++异常,则临界区对象被正确解锁,但是如果我得到任何其他类型的异常(类似于访问冲突),我有什么方法可以解锁我的关键部分?我不认为RAI​​I会在这里提供帮助,因为堆栈展开不会发生。退出函数f后,有什么办法可以防止临界区处于锁定状态吗?

5 个答案:

答案 0 :(得分:3)

编辑更新

CSingleLock的析构函数确实将解锁底层关键部分。访问冲突等称为SEH例外。至于析构函数是否会在SEH异常中运行是非常特定于环境的。您可以采取一些技巧来使这种类型的场景发挥作用。

例如,一个选项是将所有SEH异常转换为相应的C ++异常。我最近在博客上谈到了实现这一目标的技术。一旦它们都是C ++异常,那么被调用的析构函数就会得到保证。

但另一个问题是为什么要这么做呢?一旦遇到访问冲突,您的程序唯一可靠的做法就是崩溃。

答案 1 :(得分:2)

假设您正在使用MSVC,请尝试使用/EHa命令行选项进行编译,该选项将Windows的结构化异常映射到C ++异常(C ++文档有时将其称为“异步”异常)。

你应该读一下这个含义 - 我自己不使用这个选项,而且我不确定它可能有什么缺点。

您还可以尝试使用__try__except__finally关键字自行处理SEH。

答案 2 :(得分:1)

RAII在这方面提供帮助。这里最重要的是“走出范围”不一定只是堆栈展开。当正常或通过异常退出try块时,将调用析构函数。只要你的变量超出范围,就会调用析构函数。

修改

嗯,似乎编辑的问题集中在SEH(非C ++例外)上。在这种情况下,可能不会触发析构函数代码。但是,正如其他人指出的那样,大多数非C ++异常等同于应用程序崩溃。除了崩溃之外,以任何理智的方式对这些异常作出反应可能是不合理的。在这种情况下,您的应用程序将退出,无论如何您的关键部分都将被销毁。

请参阅@JaredPar的答案,找出将C SEH异常转换为Windows的C ++异常的良好解决方案。

答案 3 :(得分:0)

如果您确实需要您的应用程序在特定代码区域执行访问冲突时生存,您应该考虑在单独的进程中使用该代码。

如果代码试图读取或写入不允许的地方,有什么办法阻止它写入应用程序内存的其他部分,导致各种令人讨厌的问题?

答案 4 :(得分:0)

AFAIK,你NEVER应该使用CCriticalSection或任何MFC同步对象。