我编写了一个自定义异常类来处理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”。奇怪的部分是:当我取消注释方法的倒数第二行时,它工作得很好,即我在终端上得到两次相同的消息。我做错了什么?
答案 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.
};