从std :: exception的`what`返回一个动态字符串

Sté*_*hen 18 c++ const exception

在这一点上我确信我应该std::exception为我的所有异常抛出需求创建子类.现在我正在研究如何覆盖该what方法.

我面临的情况,如果字符串what返回是动态的,那将非常方便.例如,某些代码解析XML文件,并向错误消息添加位置或行号对我很有用.

我试图遵循Boost Exception处理指南.

我想知道的是什么:

  • what返回一个const char *,这意味着任何捕手都可能不会释放该字符串.所以我需要一些其他的地方来存储结果,但那会是哪里?(我需要线程安全.)

  • what还包括throw()其签名.虽然我可以阻止我what扔任何东西,但在我看来,这种方法真的不适合任何过于动态的东西.如果what不是正确的地方,那么我应该在哪里做这个呢?


从我到目前为止得到的答案看来,实现这一目标的唯一方法是将字符串存储在异常中.Boost指南建议不要这样做,这对我来说很困惑,因为std::runtime_error就是这样.

即使我使用的是C字符串,我也必须使用静态大小的缓冲区,或者进行内存管理也会失败.(我想知道这实际上是否是std::string复制构造函数中唯一可能出错的东西.这意味着我不会使用动态分配的C字符串获得任何东西.)

还有其他选择吗?

Unc*_*ens 17

我的异常类通常除了构造函数之外没有任何东西,并且看看这些行:

class MyEx: public std::runtime_error 
{
public: 
    MyEx(const std::string& msg, int line): 
        std::runtime_error(msg + " on line " + boost::lexical_cast<string>(line)) 
    {} 
}; 
Run Code Online (Sandbox Code Playgroud)

一个任意的例子,但它是处理what()消息管理的基类.

但是,如果您愿意,在将构造函数体中的消息放在一起之后,您也可以只分配异常对象的基本部分.

#include <stdexcept>
#include <string>
#include <sstream>

class MyEx: public std::runtime_error
{
public:
    MyEx(const std::string& msg, int line):
        std::runtime_error("")
    {
        std::stringstream ss;
        ss << msg << " on line " << line;
        static_cast<std::runtime_error&>(*this) = std::runtime_error(ss.str());
    }
};

#include <iostream>
int main()
{
    try {
        throw MyEx("Evil code", __LINE__);
    }
    catch (const std::exception& e) {
        std::cout << e.what() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,关于boost的指导方针,也许您应该注意数字数据(位置和线)最好通过其他方法作为数字提供的点.准则说要少担心这个what()消息.


Mar*_*som 6

Boost的指导原则似乎基于两个假设:复制异常对象可能会引发另一个异常,而what()字符串不是一个强大或可靠的工具.如果您正在编写一个可以在各种环境中广泛使用的库,这些都是有效的问题.如果您更好地了解如何使用例外,您可以判断这些问题是否合理或者无关紧要.编程就是一系列的权衡,而对Boost开发人员有意义的权衡可能不适用于你.