You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::call_once实现实例方法仅调用一次时的错误排查与修复

问题

想要编写一个类,其中包含一个每个对象仅能实际执行一次的方法(可多次调用,但仅首次会执行操作)。示例代码如下:

#include <iostream>
#include <functional>
#include <mutex>
class OneCallClass
{
    private:
    std::once_flag f_once{};

    public:
    void f() 
    {
        std::call_once(f_once, 
            []() { std::cout << "First call\n"; }
        );
     }
};

int main()
{
    OneCallClass o;
    o.f();
    // o.f();
    // o.f();
}

该代码在Godbolt上运行失败,错误信息如下:

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Program terminated with signal: SIGSEGV

查阅cppreference上的std::call_once()文档后仍未发现问题,文档提到若有条件阻止std::call_once按指定执行会抛出std::system_error,但不清楚具体是什么条件。在栈上创建类实例,f_once已通过{}初始化,使用了规则零,未自定义构造函数、析构函数等。请问问题出在哪里,该如何修复?

原因分析

这个错误的核心原因是Godbolt在线编译器的运行环境默认未启用多线程支持。std::call_once依赖底层的线程同步机制(比如pthreads库),如果编译时没有链接对应的线程库,运行时就会因为无法初始化同步原语而抛出std::system_error,最终导致程序崩溃。

修复方案

在Godbolt的编译选项中添加线程库链接参数即可解决问题,具体操作:

  • 找到界面右侧的编译器选项输入框
  • 添加参数 -pthread(适用于GCC/Clang编译器)

添加参数后,编译命令会自动链接线程支持库,std::call_once就能正常工作。另外需要说明的是,你的代码逻辑本身完全正确:std::once_flag的默认初始化符合要求,std::call_once可以保证lambda仅被执行一次,多次调用f()不会重复执行操作。

内容的提问来源于stack exchange,提问作者Thomas W.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:32:30