sou*_*lie 7 c++ language-lawyer c++11
在研究内容时exception_ptr,C++ 11标准说(18.8.5/7):
在引用同一异常对象的exception_ptr对象上使用rethrow_exception不应引入数据争用.[注意:如果rethrow_exception重新抛出相同的异常对象(而不是副本),对该重新抛出的异常对象的并发访问可能会引入数据争用......
我没有找到这种奇怪的"注释"适用的情况,因为所描述的效果rethrow_exception是"抛出:p引用的异常对象"但是15.1/3,描述了抛出异常副本的一般异常抛出过程强制要求 - 初始化一个临时对象,称为异常对象."
奇怪的说明意味着rethrow_exception会跳过此复制初始化.但这真的有可能吗?
是的,这看起来像是标准的缺陷。对于重新抛出的 throw 表达式,即throw;没有操作数,15.1p8 表示:
没有操作数的throw表达式会重新抛出当前处理的异常。使用现有异常对象重新激活异常;没有创建新的异常对象。[...]
那是:
#include <exception>
#include <cassert>
int main() {
std::exception *p = nullptr;
try {
try {
throw std::exception();
} catch(std::exception &ex) {
p = &ex;
throw;
}
} catch(std::exception &ex) {
assert(p == &ex);
}
}
Run Code Online (Sandbox Code Playgroud)
如果 的实现current_exception复制了当前处理的异常对象,则无法判断是否rethrow_exception复制,但如果它引用了异常对象,那么我们可以检查:
#include <exception>
#include <iostream>
int main() {
std::exception_ptr p;
try {
try {
throw std::exception();
} catch(...) {
p = std::current_exception();
std::cout << (p == std::current_exception()) << ' ';
std::rethrow_exception(p);
}
} catch(...) {
std::cout << (p == std::current_exception()) << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
我在印刷品上尝试过的每一个实现1 1;0 0如果是复印件则允许current_exception;0 1显然是不可能的,而目前的标准似乎要求1 0。修复方法是使用类似于 15.1p8 的语言对 18.8.5p10 进行澄清,允许或强制rethrow_exception不复制exception_ptr.
大多数抛出:标准中的规范仅命名类型(抛出:)bad_alloc或使用不定冠词(抛出:类型的异常...);使用定冠词的唯一其他异常规范是 和 的规范future::get,shared_future::get因此任何解决方案都应该解决这些问题。
| 归档时间: |
|
| 查看次数: |
1867 次 |
| 最近记录: |