分段错误和RAII

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()通过文件描述符对先前未链接的文件进行支持,则可以实现这一点,但是没有这样的功能:(.

Kon*_*lph 5

所以,我要问的是为这类问题提供一个漂亮,优雅的解决方案.

对于C++和其他语言都不存在.你在这里遇到了一个基本的物理现实,而不是一个设计决定:当用户拔出插头时会发生什么?没有任何编程解决方案可以防范这种情况(好吧,重启时还原).

可以做的是捕获POSIX信号,有时您甚至可以处理它们 - 但它很有趣并且有很多警告,另外还有关于Stack Overflow细节的讨论.

在段错误之后,不应该清除大多数资源.如果你想要这样做,只需在全局数组中收集这些资源(或者更确切地说,清理处理程序),陷阱SIGSEGV,遍历处理程序中的清理例程数组(希望相关内存仍然完整),以及执行清理.

更具体地说,对于临时文件,它有助于在系统的一个临时文件夹中创建它们.据了解,这些并不总是被各自的应用程序清理,系统或用户将定期执行清理.