2017-01-18 49 views
11

鉴于这段代码:的std :: call_once的()挂在第二个电话后可赎回扔在第一次调用

#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, expected=1, 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=..., [email protected]: {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 

据我所知,这似乎是正确的行为。

这是一个海湾合作委员会的bug,只是我对std::call_once的语义困惑,或者是我的代码不正确?

+0

'gcc'和'g ++'不是一回事! –

+3

复制,看起来像一个错误。 –

+0

@ Meninx-メネンックス所以呢?一个是另一个的一部分。 – user2079303

回答

7

这看起来是GNU C++库中的一个bug。


当然这是因为即使是默认的,如果您尝试使用所提供的在线编译器(Coliru):)它使用并行线程

这个错误发生在G ++ Linux实现std::call_onceexample from cppreference将挂起的错误。我感到困惑的是,this Wandbox example运行得很好。我检查的libstdc++版本:

  • Wandbox:GLIBCXX: 20130411
  • Coliru:GLIBCXX: 20161221

因此,我认为这是一个错误libstdc++,大概this one,或者更准确地说this one

相关问题