c++ RAII析构函数异常
c++ RAII destructor exception
据我所知,RAII是指在tor中获取资源并在tor中释放资源。
tor获取一些资源,并且可能失败,导致异常。dr会释放资源,也会失败,但是dr的exception是foobar,所以没有异常。
class A {
A() throw(Ex) { // acquire resources }
~A() throw() { // release resources }
}
因此,如果类A的用户应该意识到A的反初始化中发生的错误,我可以将反初始化外包给一个抛出的函数,该函数从一个吞下异常的医生调用:
class A {
A() throw(Ex) { // acquire resources }
~A() throw() { try {Release(); } catch(...) {} }
void Release() throw(Ex) { // release resources }
}
这样,如果用户想要释放错误的反馈,可以调用Exit(),或者当A超出作用域时(例如,在使用A时发生其他异常),可以忽略让医生做它的工作。
为了防止多次执行Exit()(首先由user显式执行,后来由dr间接执行),我必须添加init-status:
class A {
bool init;
A() throw(Ex) { init = true; // acquire resources }
~A() throw() { try {Release(); } catch(...) {} }
void Release() throw(Ex) {
if(!init) return;
init = false;
// release resources
}
}
是否有更好的方法来做到这一点,或者我是否必须在每次资源释放失败并且我想知道它时实现该模式?
释放资源不应该有任何失败的范围。例如,释放内存当然可以以一种不会抛出异常的形式实现。RAII的目的是清理资源,而不是处理大量清理导致的错误。
显然,有些清理操作可能会失败。例如,关闭一个文件可能会失败,例如,因为关闭它将刷新内部缓冲区,而这可能会失败,因为文件正在写入的磁盘已满。如果清理操作失败,可能应该有一个合适的释放操作,如果用户对报告清理过程中的错误感兴趣,他们应该使用这个方法:在正常路径中,将有机会处理任何错误。
当释放作为处理现有错误的一部分进行时,即抛出异常且未达到释放操作,任何异常都需要被析构函数吃掉。可能有一些处理方法,例如,记录抛出的异常消息,但异常不应该逃离析构函数。
总的来说,我认为如果您一直遵循RAII指导方针,那么您肯定需要在析构函数中抛出异常。
例如:关闭文件,释放互斥锁,关闭套接字连接,取消文件映射,关闭通信端口,回滚数据库事务等。在RAII破坏中做了太多的工作将会失败。
我们应该如何处理这些失败?在RAII析构函数中,我们几乎没有足够的信息来知道如何正确处理这些故障。我们只能选择忽略它或将其传递给上层。
但是,如果这些错误可以安全地忽略,为什么操作系统提供的api,如close, munmap, pthread_mutex_destroy等都返回错误码给我们?他们能简单地返回空吗?
所以我们最终不得不写一个析构函数:
CResource::~CResource() noexcept(false)
{
if (-1 == close(m_fd))
{
// ...
if (std::uncaught_exception())
{
return;
}
throw myExp(m_fd, ...);
}
// ...
}
当然,除了抛出异常,我们也可以选择自己的向上传播方法。例如,让上层组件为析构时可能抛出的每种类型注册一个回调方法,或者维护一个全局队列来存储和传递这些异常,等等。
但很明显,这些替代方案更笨拙,更难以使用。这相当于您自己重新实现异常机制。
- 在析构函数内部处理异常(但不抛出)
- 在 postOrderDelete 上调用析构函数时引发的异常
- 为什么在析构函数中引发异常时不调用重载删除
- 文件流析构函数是否可以在C++中引发异常?
- 为什么没有捕获我来自析构函数的异常
- 析构函数中的互斥锁C++在 Python 中调用 exit() 时会导致异常
- 旧代码在析构函数中引发异常
- 引发导致调用析构函数的异常会使程序崩溃
- 为什么我的析构函数中的异常没有触发 std::终止?
- 如何释放C++异常类析构函数中的变量
- 析构函数中的 C++ 异常
- 在scoped_ptr发生异常的情况下未调用析构函数
- 在由于异常而展开时处理C++析构函数中的pthread取消点
- c++中的Guard,在main中未处理异常时不调用析构函数
- 如何为析构函数指定nothrow异常说明符
- 堆栈异常处理和析构函数展开.如何使用这些信息
- 析构函数的异常调用
- 在 MSVC 中的析构函数中引发异常的异常
- 从保护类析构函数引发异常会导致 std::终止
- 清理C++异常析构函数中的代码