我见过几个类似的代码片段,如下所示:
struct MyExcept : std::exception {
explicit MyExcept(const char* m) noexcept : message{m} {}
const char* what() const noexcept override {
return message;
}
const char* message;
};
void foo() {
std::string error;
error += "Some";
error += " Error";
throw MyExcept{error.c_str()};
}
int main() {
try {
foo();
} catch (const MyExcept& e) {
// Is this okay?
std::cout << e.message << std::endl;
}
}
在评论后面的行中Is this okay?
,我们读取了分配在foo
函数使用std::string
。由于字符串是通过堆栈展开而被破坏的,这是未定义的行为吗?
如果确实是未定义的行为,如果我们替换main
与这个功能?
int main() {
foo();
}
由于没有 catch,编译器不会被迫展开堆栈,但会输出以下结果what()
在控制台中并中止程序。那么它仍然是未定义的行为吗?
是的,这是未定义的行为。您正在使用悬空指针。
void foo() {
std::string error;
error += "Some";
error += " Error";
throw MyExcept{error.c_str()};
} // << error goes out of scope here and so does the pointer returned
// from c_str()
由于没有 catch,编译器不会被迫展开堆栈,但会输出以下结果what()
在控制台中并中止程序。那么它仍然是未定义的行为吗?
由于默认实现将使用std::terminate并依次调用std::abort()
这可能仍然是未定义的行为,因为大多数标准处理程序实现将尝试取消引用what()
.
您可以安装自己的处理程序来避免这种情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)