自定义c ++异常类中消失的字符串

时间:2011-11-22 10:59:21

标签: c++ string class exception

我编写了一个自定义异常类来处理OLE自动化错误。 what()方法如下所示:

const char* OleException::what() const throw() {
    std::string res = std::runtime_error::what();
    LPTSTR errorText = NULL;
    FormatMessage(
        FORMAT_MESSAGE_FROM_SYSTEM
        | FORMAT_MESSAGE_ALLOCATE_BUFFER
        | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        hresult,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&errorText,
        0,
        NULL);
    if(NULL != errorText) {
        res = res + " - " + errorText;
        LocalFree(errorText);
    }
    //std::cout << res << std::endl;
    return res.c_str();
}

然而,当我尝试打印它在main()函数中返回的字符串时,我得到的只是字母“I”。奇怪的部分是:当我取消注释方法的倒数第二行时,它工作得很好,即我在终端上得到两次相同的消息。我做错了什么?

3 个答案:

答案 0 :(得分:3)

您的问题是自动销毁超出范围的对象

你的 std :: string res 是what()方法的本地方法,你返回一个指向其内部的指针。当你离开函数时,本地对象被破坏,你正试图使用​​现在悬空的指针。

当你从what()方法内部显示它时,没有问题,因为你在字符串被破坏之前显示它。

解决问题的一个好方法是让 std :: string res 成为异常类的数据成员。然后,只要您的异常实例未被销毁,您就可以安全地访问字符串内容。

答案 1 :(得分:1)

这是一个非常常见的错误:您正在返回一个指向本地对象创建的数据的指针,该指针在离开函数时会被销毁。

答案 2 :(得分:1)

正如其他人所指出的那样,c_str返回的指针在what返回的那一刻失效,因为ret不再存在。

解决方案是使错误消息成为类型std::string的异常类的成员,并在构造时进行格式化,而不是what。然后,您可以安全地从c_str返回。

class OleException : std::runtime_error  // just guessing here
{
    std::string msg;

  public:
    OleException()
    {
        // construct msg
    }
    const char* OleException::what() const throw() { return msg.c_str(); }
    // etc.
};