投掷,捕获,确定stl :: string.c_str()异常

时间:2011-05-04 17:48:41

标签: c++ exception-handling scope

说我写了一些函数myFunc可以抛出const char *例外:

void myFunc()
{
    int returnCode = whatever();
    if (!returnCode)
    {
        std::string msg;
        msg.append("whatever function failed");
        std::cerr << msg << std::endl; // print warning message
        throw msg.c_str(); // throw warning message as exception
    }
}

后来我就这样使用它了:

void myProgram()
{
    try
    {
        myFunc();
    }
    catch(const char* str)
    {
        // is 'str' string memory valid here?
    }
}

我意识到这对于异常使用来说并不是一个好的策略:更好地抛出并捕获异常类,而不是字符串。但我很好奇这里涉及的范围。

4 个答案:

答案 0 :(得分:1)

msg.str()会返回临时 std::string。由于在语句;的末尾删除了临时值,c_str()语句的内容在throw ... ;语句通过异常机制离开作用域终止时变为未定义。 / p>

const char*临时的生命周期显然已扩展到catch处理程序,但由于底层缓冲区消失,这无济于事。)


投掷std::string(即throw msg.str();)会起作用,临时的生命周期将按预期延长。

答案 1 :(得分:1)

实际上c_str()调用正在对一个临时(string)对象进行操作,当你捕获它时指针将无效。

不仅如此,但由于stringstreamstring可以进行分配,因此您需要确保不会因为堆问题而抛出。如果你因为内存不足而处于这种状态,那么你可能会在尝试创建异常时更加糟糕。您通常希望在特殊情况下避免堆分配。

您是否无法使用说runtime_error或创建自己的例外类型?

答案 2 :(得分:1)

请注意,如果你说过:

throw "error";

你会没事的,因为字符串文字的生命周期是程序的生命周期。但不管怎样,不要这样做!

答案 3 :(得分:1)

亚历山大·盖斯勒在his answer中没有提及的是,在创建临时字符串对象期间exception being thrown by by std::string itself 的可能性。

std::exception保证在施工期间不会抛出异常,std::string没有这样的保证。

另一种方法(对于类)是在类中声明私有std::string对象。在throw之前汇总错误消息,然后抛出c_str()。这将引发const char*异常,错误消息有效,直到从该类抛出下一个异常(这可能会再次修改错误字符串。)

可在此处找到一个简单示例:http://ideone.com/d9HhX