Using C++11 futures: Nested calls of std::async crash: Compiler/Standard library bug?
在我的实际程序中引入std::async的嵌套调用时遇到崩溃之后,我能够在下面的最小示例中重现这个问题。它经常崩溃,但不总是。你看到什么地方出错了吗,或者它是一个编译器或标准库错误?请注意,如果增加对期货的get()调用,问题仍然存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <future>
#include <vector>
int main (int, char *[])
{
std::vector<std::future<void>> v;
v.reserve(100);
for (int i = 0; i != 100; ++i)
{
v.emplace_back(std::async(std::launch::async, [] () {
std::async(std::launch::async, [] { });
}));
}
return 0;
} |
我观察到两种不同类型的车祸:(大约每五次)
百万千克1以"此应用程序已请求运行时以异常方式终止它"终止。百万千克1百万千克1抛出"std::future_error"实例后终止,what():promise已经满足。百万千克1
型
环境:
百万千克1Windows 7百万千克1百万千克1GCC版本4.8.2(i686-posix-dwarf-rev3,由Mingw-W64项目),如Qt 5.3.2所述百万千克1百万千克1命令行调用:g++ -std=c++11 -pthread futures.cpp。百万千克1百万千克1编译并在两台独立的机器上运行百万千克1
型
选项1〔2〕?可能是因为某种原因,在我的环境中,选项-pthread没有被静默地考虑在内吗?我观察到同样的行为,不管有没有这个选择。
- 在允许向量超出范围之前,您是否尝试过对每个未来调用get()?
- 是的,这不会改变任何事情。
- 你已经在使用strace或ltrace的Linux或Unix上运行过它吗?
- @理查德霍奇斯,所要做的就是把一个隐含的等待变成一个明确的等待。
- 什么样的车祸?它在哪里坠毁?fwiw在gnu/linux上可以与gcc 4.8.3一起使用,但我从未在mingw上测试过gcc的。
- @Jonathanwakely我编辑了原始问题来回答你的问题。
- 谢谢。第一个错误看起来像是一个普通的、无用的Windows错误(哦,不寻常的……好吧,我会去修复那些不寻常的代码!)但第二种情况很奇怪,在使用std::async时不应该出现。
- 因为没有人这么直截了当地说,我会评论,这是一个格式良好的符合C++ 11的程序。在标准库实现中有一个bug(race)。
- @凯西谢谢你的评论,我把它包括在了问题中。
- @casey,或者本机平台运行时,或者mingw运行时,因为相同的标准库实现在GNU/Linux上运行良好。
- 用libc++确认也可以很好地处理苹果的clang。看起来像是一个库实现问题。
- 你有没有试着和明格人一起提交一份bug报告?
- @jonathanwakely iirc第一个错误是调用abort()时发生的错误。当然,这也不是很有帮助…
- 您的编译命令是什么?您尝试过使用不同的线程库吗?
- @迪戈佩里尼我在问题中添加了编译命令。我可以使用其他什么线程库?STD::Asic来自C++ 11标准——那么你的意思是我可以改变所使用的底层实现?
- 在明威(Mingw aka EDOCX1)(5)工作良好
- @博里斯本非常感谢你尝试这个平台。您是否多次尝试过它,因为它不会出现在每次跑步中(大约每五次跑步都会出现问题)?
- @塞巴斯蒂安,我试着运行你的程序15次-没有崩溃。我甚至把main的身体包起来,从0到1000循环——结果是一样的——没有粉碎。
- @鲍里斯本,谢谢你的验证。
- 我把它报告为一个bug:sourceforge.net/p/mingw-w64/bugs/461
- fyi@sebastiank使用Apple llvm 4.2版(clang-425.0.28)(基于llvm 3.2svn)工作正常目标:x86_64-apple-darwin12.6.0线程模型:posix
- 我的钱是在比赛条件下,当未来被移动,而它的"会员"未来被"满足"
- 如果你把数字减到5或其他什么数字会发生什么?启动200个线程可能是一个问题。如果在返回0之前等待所有操作,问题是否仍然发生?
- @Makubex是的,我尝试了在返回0之前等待。这不会改变任何事情。但是无论如何,我假设等待是隐式发生的,所以不需要显式地进行。如果线程数太大,我希望出现std::system_错误异常。
- 它在vs-2013上运行良好…
- 在Windows上生成200个线程通常不是一个问题,因为Windows只对系统资源施加限制,而不是像Linux中的rlimit-propc这样的限制,而且通常您将有足够的资源来容纳200个线程,除非您有非常糟糕的PC或非常资源有限的VM…但是要使用线程,需要使用-pthread进行编译。所以它看起来像是MinGW C++运行时的一个bug。是否尝试链接到可调试版本的运行时并尝试在调试器下运行?
- @hosseinnarimanirad将问题中的错误消息更改为运行时实际报告的内容以外的内容?这根本不是个好主意。
- @你确定你的评论与这个问题有关吗?
- @Sebastiank是的,请参见编辑历史。HosseinNarimaniRad对你的问题做了一个虚假的编辑,我把它恢复到你的版本。
- @hvd谢谢你,我不认为你指的是编辑历史。
- 第二个错误似乎很有趣。似乎不知何故,这个项目可能会两次试图兑现同样的承诺,这应该是一个巨大的拒绝。
- 相关:stackoverflow.com/questions/3930700/&hellip;它似乎与您的错误相同,答案是此人也没有包含pthread。
- 您是否可以尝试将编译器更新为GCC4.9或5.1?也许您应该用std::promise来尝试一个例子,因为这似乎是这里的问题。
由于这个答案在与一些来自Lounge的人交谈之后仍然是"没有答案的",我认为从评论中可以很明显地看出,这是由于mingw/mingw-w64或pthread当时的一个实现错误造成的。使用GCC4.9.1,mingw-w64,问题不再出现。事实上,即使在4.8.2之前的版本中使用POSIX线程,上述程序似乎也能正确编译和运行。
我本人不是专家,我的猜测是,当程序出现两次试图写同一个承诺时,就会发生确切的错误,我认为这应该是一个很大的错误,因为std::async应该只写一次结果(同样,我不确定我是否在这里,其他评论和编辑很可能会澄清)。
此外,这可能是一个相关问题:STD::GCC实验实现的C++0x的未来异常
- 这个bug报告线程可能与pthread:sourceware.org/bugzilla/show_bug.cgi相关?ID=12683
- 谢谢,我可以通过GCC4.9.1,mingw-w64(在我问这个问题的时候在编译的Windows Qt发行版(我实际项目的环境)中不可用)来确认崩溃是否消失。
- 很高兴听到这个问题解决了。
- 奇怪的是,这个程序现在也可以在没有-pthread的情况下运行。
- 它似乎也出现在netbsd 7.0和gcc 4.8.4中。另请参见netbsd 7.0 amd64和crash in dsa_signature_operation::raw_sign。