c++ - QNX 上的 std::call_once 延迟初始化问题

标签 c++ multithreading c++11 lazy-initialization qnx

我的代码在 QNX 上定期崩溃。它因错误而崩溃

error reading variable: Cannot access memory at address 0x85dd6ac)

尝试访问 0x85dd6ac 对象的 std::map 成员变量时,该对象使用 std::call_once 延迟初始化。

初始化是用下面的伪代码完成的:

mutable std::aligned_storage<sizeof(A), alignof(A) >::type m_value;

void init(A *ptr)
{
    new (ptr) A();
}

inline T* data() const
{
    return reinterpret_cast<A*>(&m_value);
}

const A& get() const
{
    std::call_once(m_once_flag, init, data());
    return *data();
}

在某些时候,当访问 get() 返回的对象时,进程会崩溃。

在其他平台上,问题没有重现,调试起来非常困难。 从代码中我可以看出对象不能取消初始化,也不能在此时删除。

我怀疑 std::call_once 实现线程安全或内存排序可能存在问题。 有没有人有在 QNX 平台上使用 std::call_once 的经验或类似的错误? 我有什么想法可以找到问题吗?

最佳答案

我在 QNX 中使用 std::call_once 时也有同样的经历,但除了崩溃之外,它还会导致多线程应用程序中的死锁。我建议使用以下模式替换 std::call_once:

static std::atomic< bool > once_flag = false;
if ( !once_flag.exchange( true ) )
{
    // This part will be executed only once.
    // ...
}

更新 根据 fefe 的评论,该解决方案不满足被动执行的阻塞条件(详见 http://www.cplusplus.com/reference/mutex/call_once/)。

如果你也必须满足这一点,你应该实现更复杂的解决方案。这是一个例子:

static std::atomic< bool > once_flag = false;
static std::atomic< bool > once_call_done = false;
if ( !once_flag.exchange( true ) )
{
    // This part will be executed only once.
    // ...

    once_call_done = true;
}
else
{
    // Block until the call once part is running.
    while( !once_call_done )
    {
        sleep( 1 );
    }
}

关于c++ - QNX 上的 std::call_once 延迟初始化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36157726/

相关文章:

c++ - gcc 要求使用 -std=c++11 即使我已经在使用它

python - 强制输入()从不同的线程读取换行符并向前执行

c++ - 当宏用作变量名时,有什么方法可以跳过宏替换(在预处理期间)?

c++ - QToolBox - 展开多个项目

c# - 我应该学习Java还是应该学习C++?

multithreading - x86 保留 EFLAGS 位 1 == 0 : how can this happen?

java - 对象的成员不需要 volatile 而只需要原始成员吗?

C++ - 没有要调用的匹配函数

C++:如何创建一个临时对象,包含一个指针 - const 或非常量,具体取决于上下文?

c++ - 如何获取基于for循环的范围内对象的地址?