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

时间:2021-10-28 15:04:35

I have a object of CCriticalSection in my class to synchronize the exceptions to a method. I use it with CSingleLock object like this:

我的类中有一个CCriticalSection对象,用于将异常同步到方法。我像这样使用CSingleLock对象:

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

   }

  catch(SomeException )
  {
  }

  catch(...)
  {
  }

}

The critical section object is properly unlocked if any of the statement throws a C++ exception, however if I get any other type of exception (something like a access violation) is there any way I can unlock my critical section? I don't think RAII will help here as the stack unwinding doesn't happen. Is there any thing I can do to prevent the critical section being in locked state after exiting the function f?

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

5 个解决方案

#1


EDIT Update

The destructor of CSingleLock will indeed unlock the underlying critical section. Access violations and the like are called SEH exceptions. As to whether or not the destructor will run in the face of an SEH exception is very environment specific. There are tricks you can do to make this type of scenario work.

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

For instance, one option is to translate all SEH exceptions into a corresponding C++ exception. I blogged recently on the technique to accomplish this. Once they're all C++ exceptions then the destructor being called is guaranteed.

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

But another question is why bother doing this? Once you're faced with at access violation the only thing your program can reliably do is crash.

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

#2


Assuming you're using MSVC try compiling with the /EHa command line option which maps Windows' structured exceptions to C++ exceptions (the C++ docs sometimes call them 'asynchronous' exceptions).

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

You should read up on the implications of this - I don't use the option myself, and I'm not sure what the drawbacks might be.

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

You could also try using the __try, __except, __finally keywords to handle SEH yourself.

您也可以尝试使用__try,__ except,__ finalally关键字来自行处理SEH。

#3


RAII does help here. The most important thing to not here is "going out of scope" is not necessarily just stack unwinding. When the try block is exited, either normally or through an exception, the destructor will be called. Anytime your variable goes out of scope its destructor is invoked.

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

Edit

Hmm it appears the question has been edited to focus on SEH (non C++ exceptions). In this case the destructor code might not be fired. However, as others have pointed out, most of the non-C++ exceptions are equivalent to application crashes. It may not be reasonable to react to these exceptions in any sane way other than to crash. In this case your app is exited and your critical section will be destroyed anyway.

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

See @JaredPar's answer for a good solution for translating C SEH exceptions to C++ exceptions for Windows.

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

#4


If you really need your application to survive when a particular area of code performs an access violation, you should consider having that code in a separate process.

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

If code is trying to read or write to places it's not allowed, what's to stop it writing into other parts of your application's memory, causing all sorts of nasty problems?

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

#5


AFAIK, you NEVER should use CCriticalSection nor any MFC synchronization object.

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

#1


EDIT Update

The destructor of CSingleLock will indeed unlock the underlying critical section. Access violations and the like are called SEH exceptions. As to whether or not the destructor will run in the face of an SEH exception is very environment specific. There are tricks you can do to make this type of scenario work.

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

For instance, one option is to translate all SEH exceptions into a corresponding C++ exception. I blogged recently on the technique to accomplish this. Once they're all C++ exceptions then the destructor being called is guaranteed.

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

But another question is why bother doing this? Once you're faced with at access violation the only thing your program can reliably do is crash.

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

#2


Assuming you're using MSVC try compiling with the /EHa command line option which maps Windows' structured exceptions to C++ exceptions (the C++ docs sometimes call them 'asynchronous' exceptions).

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

You should read up on the implications of this - I don't use the option myself, and I'm not sure what the drawbacks might be.

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

You could also try using the __try, __except, __finally keywords to handle SEH yourself.

您也可以尝试使用__try,__ except,__ finalally关键字来自行处理SEH。

#3


RAII does help here. The most important thing to not here is "going out of scope" is not necessarily just stack unwinding. When the try block is exited, either normally or through an exception, the destructor will be called. Anytime your variable goes out of scope its destructor is invoked.

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

Edit

Hmm it appears the question has been edited to focus on SEH (non C++ exceptions). In this case the destructor code might not be fired. However, as others have pointed out, most of the non-C++ exceptions are equivalent to application crashes. It may not be reasonable to react to these exceptions in any sane way other than to crash. In this case your app is exited and your critical section will be destroyed anyway.

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

See @JaredPar's answer for a good solution for translating C SEH exceptions to C++ exceptions for Windows.

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

#4


If you really need your application to survive when a particular area of code performs an access violation, you should consider having that code in a separate process.

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

If code is trying to read or write to places it's not allowed, what's to stop it writing into other parts of your application's memory, causing all sorts of nasty problems?

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

#5


AFAIK, you NEVER should use CCriticalSection nor any MFC synchronization object.

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