派生自std :: exception

cpp*_*nda 7 c++ exception-handling

我想从std :: exception派生,以便将特定信息添加到我的日志文件中,但我无法想象如何从std :: exception访问.what().

此外,我知道在我的异常处理程序中创建一个字符串是不安全的,但我不是这个主题的专家,那么什么是更安全的替代品?

struct Exception : public std::exception, private boost::noncopyable
{
    public:
        Exception(std::string msg)
            : message(msg)
        {}
        ~Exception()
        {}

        virtual const char* what() const throw 
        {
            std::string what = message + // and now what? base.what()
            LOG(what); // write to log file
            return what.c_str();
        }

    private:
        std::string message;
};
Run Code Online (Sandbox Code Playgroud)

编辑:我真的以错误的方式问我的问题.我对安全性很感兴趣,我只是觉得拥有更多的日志数据会很好.我错了.

现在,我并没有因为消息字符串抛出bad_alloc而变得如此偏执以防万一之前有一个bad_alloc,我宁愿有一个简洁的消息.据说我改写了一些东西:

struct Exception : public std::exception
{
    public:
        Exception(std::string msg)
            : message(msg)
        {}
        ~Exception()
        {}

        virtual const char* what() const throw 
        {
            LOG(what); // write to log file
            return what.c_str();
        }

    private:
        std::string message;
};
Run Code Online (Sandbox Code Playgroud)

现在还有任何关于该代码的大问题吗?LOG()抛出std :: exception我出错了,因为我不想通过派生异常类进行无限循环的日志调用,并且该类再次调用log会再次导致相同的异常.这会像我想要的那样工作,或者我的派生类中的日志记录异常会调用terminate()还是导致核心转储?

And*_*ron 9

编辑:自从写这个答案,我偶然发现了Boost文档中的错误和异常处理部分.我会建议这个答案的文件.


首先,让您的例外不可复制是一个坏主意.当你写一些如

// could be any exception, doesn't matter.
throw Exception(...);
Run Code Online (Sandbox Code Playgroud)

运行时将该对象的副本创建到特殊位置.有些编译器可能会优化它并在该位置创建原始对象,但是C++编程语言说这是一个副本,我也相信这是标准所说的,尽管我不确定.您可能会在当前环境中侥幸成功,但情况可能并非总是如此.

然后,其他一切都取决于你对角落案件的偏执程度.

内存分配部分在异常子句(即构造函数)中大多是片状的.如果此内存分配失败(即std::bad_alloc抛出),则有两种可能性,具体取决于您编写throw语句的方式:

  1. std::stringthrow语句之前创建,std::bad_alloc替换您认为会引发的异常,问题是严重报告的.
  2. std::string是在构造函数调用中内联创建的.如果这被标准认为是"在异常处理期间",std::unexpected()/std::terminate()则会调用并且您基本上会获得核心转储.

在任何情况下,您似乎都无法获得报告错误所需的效果.

我总是建议创建某种临时状态,它不会在构造函数中分配内存并等待调用std::what()来创建报告错误的字符串,但这可能仍会导致情况#1.您可以使用一些编译时确定的缓冲区大小来确保不会发生.

许多人会告诉你他们在构造函数中分配字符串时从来没有遇到过问题,因为std::bad_alloc除非最初的异常是std::bad_alloc第一位的,否则它不太可能会被提升.因此,这取决于你的偏执程度.