std::使用来自本地对象的消息时发生异常
std::exception using message from local object
下面的代码是否安全地使用自定义消息抛出异常?
#include <exception>
#include <sstream>
#include <string>
#include <iostream>
int main() {
try {
std::ostringstream msg;
msg << "give me " << 5;
throw std::exception(msg.str().c_str());
} catch (std::exception& e) {
std::cout << "exception: " << e.what();
}
}
与VC++-2008这给出:
exception: give me 5
但现在我想知道为什么来自本地对象msg
的消息"give me 5"在catch块中仍然可用?在打印消息时,流和临时字符串对象都应该已删除?顺便说一句:这种为异常生成消息的方式似乎也适用于多个函数,如果在打印异常之前在catch块中分配了新内存,也适用。
或者有必要定义一个带有std::string成员的自定义异常类,以便在打印消息之前安全地保存消息
它非常安全。将C字符串作为单个参数的构造函数生成该字符串的副本。使用一个C字符串和一个长度参数的构造函数,可以指定不分配内存,并存储指向该字符串的指针(忽略长度参数(。
请注意,这两个构造函数是std::exception
类的扩展,不是标准的。还要注意,将C字符串作为单个参数的构造函数没有标记为显式。
还好
根据§15.1/3:
抛出异常副本初始化(8.5、12.8(临时对象,调用了异常对象。
和§15.1/4:
异常对象的内存分配在未指定的除非3.7.4.1中另有说明。如果处理程序通过重新抛出退出,控制被传递给同一异常的另一个处理程序。这个异常对象在最后一个活动之后被销毁异常的处理程序通过除重新思考之外的任何方式退出。。。
所以在throw expression
:之后
表达式将被复制(复制构造函数将创建新对象(,您不必担心本地对象。
关于你担心的msg
和const char*
。。。这是微软的实现:
exception::exception(const char * const & _What)
: _Mywhat(NULL), _Mydofree(false)
{
_Copy_str(_What);
//^^^^^^^^^^^^^^^^^
}
void exception::_Copy_str(const char * _What)
{
if (_What != NULL)
{
const size_t _Buf_size = strlen(_What) + 1;
_Mywhat = static_cast<char *>(malloc(_Buf_size));
if (_Mywhat != NULL)
{
_CRT_SECURE_STRCPY(const_cast<char *>(_Mywhat), _Buf_size, _What);
//^^^^^^^^^^^^^^^^^^
_Mydofree = true;
}
}
}
它复制_What
,而不仅仅是存储指针。
std::exception
在标准中没有采用char*的构造函数。您正在使用MS扩展。为了使其具有可移植性和安全性,请改用std::runtime_error
,您可以在ctor中将std::string
传递给它。
相关文章:
- 从函数(不抛出函数)返回异常以进行消息格式化?
- C++MSVC-显示未捕获的异常消息
- 奇怪的消息 (_Base_bitset::_M_do_to_ulong) 从溢出异常处理程序中打印出来
- 从处理程序捕获时如何获取 Ada 异常消息C++?
- 核心消息传递中未处理的异常.dll在程序关闭期间
- C++未显示自定义异常消息
- 自定义异常中的消息已损坏
- 异常消息为空
- 捕获加速异常并提取其消息
- 运行时异常消息而不扩展 std::exception
- 异常是否应具有标志/消息,或者每个错误应具有异常类型
- 获取谷歌测试异常抛出消息
- 如何抛出带有变量消息的 std::异常
- 未决定是使用异常还是报告错误消息
- 从ASSERT_THROW获取异常消息
- 加密++异常调用消息结束
- 使用 GoogleTest 验证异常消息
- 如果引发异常,则使外部C++函数返回一条消息
- 如何与调试器通信或更改异常消息
- 系统消息未处理的异常