Gre*_*ape 5 c++ posix exception raii segmentation-fault
这更像是一种哲学类型的问题.
在C++中,我们有很好的闪亮成语 - RAII.但我常常认为它不完整.它与我的应用程序可以用SIGSEGV杀死的事实不太一致.
我知道,我知道,像你这样的程序是不正确的.但令人遗憾的是,在POSIX(特别是Linux)上,您可以分配超出物理内存限制并在执行过程中满足SIGSEGV,使用正确分配的内存.
你可能会说:"应用程序死了,你为什么要关心那些没有被调用的糟糕的析构函数?".遗憾的是,有些资源在应用程序终止时不会自动释放,例如文件系统实体.
我现在非常厌倦了设计黑客,破坏良好的应用程序设计以应对这一点.所以,我要问的是为这类问题提供一个漂亮,优雅的解决方案.
似乎我错了,Linux应用程序被内核寻呼机杀死.在这种情况下,问题仍然是相同的,但申请死亡的原因是不同的.
代码段:
struct UnlinkGuard
{
UnlinkGuard(const std::string path_to_file)
: _path_to_file(path_to_file)
{ }
~UnlinkGuard() {
unlink();
}
bool unlink() {
if (_path_to_file.empty())
return true;
if (::unlink(_path_to_file.c_str())) {
/// Probably some logging.
return false;
}
disengage();
return true;
}
void disengage() {
_path_to_file.clear();
}
private:
std::string _path_to_file;
};
void foo()
{
/// Pick path to temp file.
std::string path_to_temp_file = "...";
/// Create file.
/// ...
/// Set up unlink guard.
UnlinkGuard unlink_guard(path_to_temp_file);
/// Call some potentially unsafe library function that can cause process to be killed either:
/// * by a SIGSEGV
/// * by out of memory
/// ...
/// Work done, file content is appropriate.
/// Rename tmp file.
/// ...
/// Disengage unlink guard.
unlink_guard.disengage();
}
Run Code Online (Sandbox Code Playgroud)
成功后我使用文件.失败时我希望丢失此文件.
如果POSIX支持link()
通过文件描述符对先前未链接的文件进行支持,则可以实现这一点,但是没有这样的功能:(.
所以,我要问的是为这类问题提供一个漂亮,优雅的解决方案.
对于C++和其他语言都不存在.你在这里遇到了一个基本的物理现实,而不是一个设计决定:当用户拔出插头时会发生什么?没有任何编程解决方案可以防范这种情况(好吧,重启时还原).
您可以做的是捕获POSIX信号,有时您甚至可以处理它们 - 但它很有趣并且有很多警告,另外还有关于Stack Overflow细节的讨论.
在段错误之后,不应该清除大多数资源.如果你想要这样做,只需在全局数组中收集这些资源(或者更确切地说,清理处理程序),陷阱SIGSEGV,遍历处理程序中的清理例程数组(希望相关内存仍然完整),以及执行清理.
更具体地说,对于临时文件,它有助于在系统的一个临时文件夹中创建它们.据了解,这些并不总是被各自的应用程序清理,系统或用户将定期执行清理.