c++ - RAII 获取在销毁过程中捕获的错误的方法

标签 c++ error-handling destructor raii stack-unwinding

在维基百科上一个典型的文件 I/O RAII 示例中,关闭文件时发生的任何错误都被吞没了:

#include <iostream>
#include <string> 
#include <fstream>
#include <stdexcept>

void write_to_file (const std::string & message) {
    // try to open file
    std::ofstream file("example.txt");
    if (!file.is_open())
        throw std::runtime_error("unable to open file");

    // write message to file
    file << message << std::endl;

    // file will be closed when leaving scope (regardless of exception)
}

似乎没有办法判断file自动关闭时是否发生了错误;显然,当 file 在范围内时,只能调用 file.rdstate()

我可以手动调用 file.close() 然后检查错误,但我必须在从范围返回的每个地方都这样做,这违背了 RAII 的目的。

有些人评论说析构函数中只会发生文件系统损坏等不可恢复的错误,但我不相信这是真的,因为据我所知,析构函数会在关闭文件之前刷新文件,并且在刷新时可能会发生可恢复的错误。

那么是否有一种通用的 RAII 方法来获取销毁过程中发生的错误?我读到从析构函数中抛出异常是危险的,所以这听起来不像是正确的方法。

我能想到的最简单的方法是注册一个回调函数,如果在销毁过程中发生任何错误,析构函数将调用该回调函数。令人惊讶的是,似乎没有 ios_base::register_callback 支持的事件。这似乎是一个重大疏忽,除非我误解了什么。

但也许回调是在现代类设计中销毁期间获得错误通知的最常见方式?

我假设在析构函数中调用任意函数也是危险的,但也许将调用包装在 try/catch block 中是完全安全的。

最佳答案

您可能会部分处理析构函数中的失败情况:

class Foo {
public:
    Foo() : count(std::uncaught_exceptions()) {}
    ~Foo() noexcept(false)
    {
        if (std::uncaught_exceptions() != count) {
            // ~Foo() called during stack unwinding
            // Cannot throw exception safely.
        } else {
            // ~Foo() called normally
            // Can throw exception
        }
    }
private:
    int count;
};

关于c++ - RAII 获取在销毁过程中捕获的错误的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48880660/

相关文章:

c++ - 为什么允许在初始化列表中从 const 指针到 const 转换为 const 指针到非常量

c++ - 有没有办法不使用命名空间中的项目?

c++ - 如何添加枚举类型来引用数组

c++ - std::auto_ptr 与 std::tr1::shared_ptr

swift - “ fatal error :在展开可选值时意外发现nil”是什么意思?

c++ - 错误 : Heap block at X modified

Java输出控制台错误消息到文件?

c++ - vector 分配崩溃

c++ - 使用自动存储的指针应该包含析构函数吗?

c++ - 非指针成员变量的虚析构函数