我的类中有一个CCriticalSection对象,用于将异常同步到方法。我将它与CSingleLock对象一起使用,如下所示:
void f()
{
try
{
CSingleLock lock(&m_synchronizer, TRUE);
.....
.....
}
catch(SomeException )
{
}
catch(...)
{
}
}
如果任何语句抛出C ++异常,则临界区对象被正确解锁,但是如果我得到任何其他类型的异常(类似于访问冲突),我有什么方法可以解锁我的关键部分?我不认为RAII会在这里提供帮助,因为堆栈展开不会发生。退出函数f后,有什么办法可以防止临界区处于锁定状态吗?
答案 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同步对象。