RAII方法来获取销毁过程中捕获的错误 [英] RAII way to get errors that are caught during destruction

查看:57
本文介绍了RAII方法来获取销毁过程中捕获的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Wikipedia上用于文件I/O的RAII的典型示例中,吞下了关闭文件时发生的任何错误:

  #include< iostream>#include< string>#include< fstream>#include< stdexcept>void write_to_file(const std :: string& message){//尝试打开文件std :: ofstream文件("example.txt");如果(!file.is_open())抛出std :: runtime_error(无法打开文件");//将消息写入文件文件<<消息<<std :: endl;//离开范围时,文件将关闭(无论是否发生异常)} 

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

我可以手动调用 file.close()然后检查错误,但是我必须在从示波器返回的每个位置执行此操作,这违背了RAII的宗旨./p>

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

那么,有一种常见的RAII方法来获取销毁期间发生的错误吗?我读到从析构函数中抛出异常是危险的,因此听起来不像是正确的方法.

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

但是在现代类设计中,也许回调是最常见的在销毁过程中通知错误的方法?

我认为在析构函数中调用任意函数也是危险的,但是也许将调用包装在 try/catch 块中是完全安全的.

解决方案

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

  Foo类{上市:Foo():count(std :: uncaught_exceptions()){}〜Foo()noexcept(假){if(std :: uncaught_exceptions()!= count){//〜展开堆栈时调用的〜Foo()//无法安全地引发异常.} 别的 {//〜Foo()正常调用//可以抛出异常}}私人的:整数计数}; 

In a typical example of RAII for File I/O on Wikipedia, any errors that occur when closing the file are swallowed:

#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)
}

It seems there is no way to determine if an error occurred when file is automatically closed; obviously one can only call file.rdstate() while file is on scope.

I could call file.close() manually and then check for an error, but I would have to do that at every place I return from the scope, which defeats the purpose of RAII.

Some have commented that only unrecoverable errors like file system corruption can occur within the destructor, but I don't believe that's true because AFAIK the destructor flushes the file before closing it, and recoverable errors could occur while flushing.

So is there a common RAII way to get errors that occur during destruction? I read that throwing exceptions from destructors is dangerous so that doesn't sound like the right approach.

The simplest way I can think of is to register a callback function that the destructor will call if any errors occur during destruction. Surprisingly it doesn't seem like there is an event for this supported by ios_base::register_callback. That seems like a major oversight, unless I misunderstand something.

But perhaps a callback is the most common way to get notified of errors during destruction in modern class designs?

I assume calling an arbitrary function in a destructor is also dangerous, but perhaps wrapping the call in a try/catch block is completely safe.

解决方案

You might partially handle the case of failure in destructor:

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;
};

这篇关于RAII方法来获取销毁过程中捕获的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆