RAII方法来获取销毁过程中捕获的错误 [英] RAII way to get errors that are caught during destruction
问题描述
在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屋!