【发布时间】:2015-08-01 22:47:23
【问题描述】:
我刚刚从 Visual Studio 2013 升级到 2015,我遇到了一堆问题,这些问题过去在 2013 年可以工作,但在 2015 年就不行了。
例如,这是一个让我难过的问题。我用原始代码创建了一个测试用例。
基本上,代码通过 std::async() 在线程中运行一些操作。在线程内,可能会抛出异常 (A),该异常应放置在 std::async() 返回的未来对象中。奇怪的是,在(B)中,调用了 Ex 的析构函数,但对象仍然被抛出。在 try 块中,当 ex (D) 变量离开分数时,如果 'mInts' 向量 (X) 是成员,则程序将崩溃。如果我将“mInts”注释掉,如下所示,我仍然会出现奇怪的行为。例如,下面的代码是这样打印的:注意构造函数被调用了 1 次,而析构函数被调用了 4 次:
输出:
constructor
destructor
before exception
after exception
destructor
has exception
destructor
destructor
代码:
using FutureList = std::vector<std::future<void>>;
struct Ex {
Ex() {
std::cout << "constructor\n";
}
Ex(const Ex&) = delete;
Ex(Ex&&) {
std::cout << "move constructor";
}
~Ex() {
std::cout << "destructor\n";
}
void operator=(const Ex&) {
std::cout << "assign\n";
}
// std::vector<int> mInts; (X)
};
TEST(Explore, Test1) {
FutureList futures;
futures.push_back(
std::async(std::launch::async, []() {
throw Ex(); // (A)
}));
std::exception_ptr ex;
for (auto& i : futures) {
try {
i.get(); // (B)
std::cout << "Doesn't get here.\n";
}
catch (...) { // (C)
std::cout << "before exception\n";
ex = std::current_exception(); // (D)
std::cout << "after exception\n";
}
}
if (ex) {
std::cout << "has exception\n";
}
}
【问题讨论】:
-
多么奇怪。我刚刚谈到另一个问题,关于 VC++ 6.0 错误,它两次调用异常对象的析构函数。无论如何,既然您已经允许 VC++ 对复制构造函数的错误调用,那么构造函数和析构函数调用之间是否存在相同的差异?
-
@Cheers 和 hth。 - Alf:现在没有差异。打印输出的问题是因为复制构造函数中没有打印。我添加了一些,构造函数/析构函数计数匹配。
-
如果您能写下您的发现作为您问题的答案并接受它,那就太好了。如果您想知道,那完全可以。它可以帮助其他人,并为您提供一些急需的声望点。 ;-)
-
请抽象出这个
TEST宏并添加一个main函数,这样我们就可以自己重现您的问题。 stackoverflow.com/help/mcve -
@bogdan - 你继续,报告它。