c++ - std::call_once() 在 callable 抛出第一次调用后在第二次调用时挂起

标签 c++ c++11 g++ libstdc++ compiler-bug

给定这段代码:

#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=..., __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

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

这是 GCC 错误吗,只是我对 std::call_once 的语义感到困惑,还是我的代码不正确?

最佳答案

这看起来是 GNU C++ 库中的错误。


这肯定是一个错误,因为即使是默认的 std::call_once example from cppreference如果您尝试使用提供的在线编译器 (Coliru) 将会挂起:)

该错误发生在使用 pthreads 的 g++ linux 实现中。令我困惑的是 this Wandbox example运行得很好。我检查了 libstdc++ 的版本:

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

因此我认为这是一个 libstdc++ 错误,可能是 this one ,或更准确地说 this one .

关于c++ - std::call_once() 在 callable 抛出第一次调用后在第二次调用时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41717579/

相关文章:

c++ - 与 .so 文件链接 (webkit)

c++ - 当类型包含具有给定名称和类型的静态变量时启用_if 函数

c++ - 将 vector<unique_ptr<T>> 转换为 vector<unique_ptr<const T>>

gcc - Makefile无缘无故删除目标文件

c++ - BOOST-ASIO 阻塞服务器不响应阻塞客户端?

c++ - 将矩阵附加到 STL 矩阵(2d std::vector)

c++ - 地址 sanitizer 失败

c++ - Boost 预处理器中的迭代限制

c++ - C++中的空间泄漏?

c++ - 创建一个指向纯虚类的新指针