2017-01-18 6 views
11

Given ten kawałek kodu:std :: call_once() wisi na drugim wywołaniu po wywoływalnym rzucił na pierwsze wezwanie

#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); 
} 

Kiedy skompilowany z g++ -std=c++11 -pthread -ggdb mam wyjścia:

Throwing 
Caught 42 

po którym proces zawiesza:

#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 

Ale gdy skompilowany z clang++ -std=c++11 -pthread -ggdb uzyskać:

Throwing 
Caught 42 
Throwing 
Caught 42 
Not throwing 
Returning 
Returning 
Returning 

O ile mi wiadomo, wydaje się to być prawidłowe zachowanie.

Czy jest to błąd GCC, tylko że jestem zdezorientowany przez semantykę std::call_once, czy mój kod jest niepoprawny?

+0

'gcc' i' g ++ 'to nie to samo! –

+3

Replikowane, wygląda jak błąd. –

+0

@ Meninx- メ ネ ン ッ ク ス co z tego? Jedna jest częścią drugiej. – user2079303

Odpowiedz

7

To wygląda na błąd w bibliotece GNU C++.


Z pewnością jest to problem, ponieważ nawet domyślnie std::call_onceexample from cppreference zawiśnie jeśli spróbujesz użyć dostarczonego kompilatora online (Coliru) :)

Błąd dzieje się w g ++ wdrożenie Linuksa, który używa pthreads. Zaskoczyło mnie to, że this Wandbox example działa dobrze. Sprawdziłem wersje libstdc++:

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

dlatego uważam, że jest to libstdc++ błąd, prawdopodobnie this one, a dokładniej this one.

Powiązane problemy