我的代码在 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/