Lig*_*ica 30 c++ exception language-lawyer c++11
标准库缺陷#254,它涵盖了新的异常构造函数的添加:
std::logic_error::logic_error(const char* what_arg);
std::runtime_error::runtime_error(const char* what_arg);
// etc.
Run Code Online (Sandbox Code Playgroud)
作为基本原理,存储std::strings打开了一些与可能存在问题的内存分配有关的蠕虫.
然而,在休息室中orlp开始讨论之后,我觉得除非标准要求what_arg只是一个字符串文字(或指向静态存储持续时间的其他缓冲区的指针),否则它必须执行无论如何都要复制C-string,以保持成员函数的良好定义what().
那是因为:
void bar() {
char buf[] = "lol";
throw std::runtime_error(buf);
}
void foo() {
try {
bar();
}
catch (std::exception& e) {
std::cout << e.what() << '\n'; // e.what() points to destroyed data!
}
}
Run Code Online (Sandbox Code Playgroud)
但我看不到任何这样的任务.事实上,异常对象是否深层复制what_arg似乎完全没有指定.
如果他们这样做,那么首先添加重载(消除额外分配)的大部分理由似乎完全是空的.
这可能是标准缺陷,还是我在这里遗漏了什么?
这只是"程序员:不要在任何地方传递悬空指针"的情况吗?
Jer*_*fin 19
这允许(或者至少显然是为了方便 - 在下面看到更多)实现,以消除副本,如果它可以检测到(通过本身不是标准化的方式)传递的是字符串文字或静态的其他内容储存期限.
例如,假设编译器将所有字符串文字汇集到一个由__string_literals_begin和分隔的范围内__string_literals_end.然后std::exception它在构造函数中的某个地方可能有一般顺序的代码:
namespace std {
exception::exception(char const *s) {
if (in_range(s, __string_literals_begin, __string_literals_end)) {
stored_what = s;
destroy_stored_what = false;
}
else {
stored_what = dupe(s);
destroy_stored_what = true;
}
// ...
}
exception::~exception() {
if (destroy_stored_what)
delete_string(stored_what);
}
Run Code Online (Sandbox Code Playgroud)
链接DR中的最终评论指出:
[Oxford:提议的解决方案只是解决了使用const char*和字符串文字构造异常对象的问题,而无需显式包含或构造std :: string.]
因此,根据当时的评论,委员会意识到这些超载并未满足所有需求,但确实解决了(至少被认为是)需求.
(几乎)确实如果实施可以提供这些超载,即使它们没有被标准规定 - 尽管如此,委员会似乎已经确信添加它们对于上述情况主要(如果不是唯一的话)是有用的 - - 当字符串文字传递给ctor时,只有一个浅拷贝.
| 归档时间: |
|
| 查看次数: |
2092 次 |
| 最近记录: |