给定这段代码:
- #include <mutex>
- #include <iostream>
- void f(bool doThrow) {
- if (doThrow) {
- std::cout << "Throwing" << std::endl;
- throw 42;
- }
- std::cout << "Not throwing" << std::endl;
- }
- std::once_flag flag;
- void g(bool doThrow) {
- try {
- std::call_once(flag,f,doThrow);
- std::cout << "Returning" << std::endl;
- } catch (int i) {
- std::cout << "Caught " << i << std::endl;
- }
- }
- int main() {
- std::once_flag flag;
- g(true);
- g(true);
- g(false);
- g(true);
- g(false);
- }
当编译g -std = c 11 -pthread -ggdb时,我得到输出:
- Throwing
- Caught 42
之后进程挂起:
- #0 0x000003fff7277abf in futex_wait (private=0,expected=1,futex_word=0x2aaaacad144 <flag>) at ../sysdeps/unix/sysv/linux/futex-internal.h:61
- #1 futex_wait_simple (private=0,futex_word=0x2aaaacad144 <flag>) at ../sysdeps/nptl/futex-internal.h:135
- #2 __pthread_once_slow (once_control=0x2aaaacad144 <flag>,init_routine=0x3fff7a8d870 <std::__once_proxy()>) at pthread_once.c:105
- #3 0x000002aaaaaab06f in __gthread_once (__once=0x2aaaacad144 <flag>,__func=0x3fff7a8d870 <std::__once_proxy()>) at /usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5/x86_64-pc-linux-gnu/bits/gthr-default.h:699
- #4 0x000002aaaaaab6c8 in std::call_once<void (&)(bool),bool&> (__once=...,__f=@0x2aaaaaab08c: {void (bool)} 0x2aaaaaab08c <f(bool)>) at /usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include/g++-v5/mutex:738
- #5 0x000002aaaaaab192 in g (doThrow=true) at test.cpp:17
- #6 0x000002aaaaaab287 in main () at test.cpp:27
但是当编译时使用clang -std = c 11 -pthread -ggdb我得到:
- Throwing
- Caught 42
- Throwing
- Caught 42
- Not throwing
- Returning
- Returning
- Returning
据我所知,这似乎是正确的行为.
解决方法
这看起来是GNU C库中的一个错误.
当然这是一个错误,因为即使默认std :: call_once example from cppreference将挂起,如果您尝试使用提供的在线编译器(Coliru):)
该错误发生在使用pthread的g linux实现中.令我困惑的是this Wandbox example跑得很好.我检查了libstdc的版本:
> WandBox:GLIBCXX:20130411
> Coliru:GLIBCXX:20161221