std::call_once QNX 延迟初始化问题
std::call_once lazy initialization issue on 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 的经验或类似的错误?
有什么办法可以找到问题吗?
问题出在 std::call_once。这是实施中的错误。
临时替换为 mutex 解决了这个问题。
没有更多时间深入研究细节,但希望这些信息能帮助遇到类似问题的人。
感谢大家的评论!
我在 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 );
}
}
我的代码在 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 的经验或类似的错误?
有什么办法可以找到问题吗?
问题出在 std::call_once。这是实施中的错误。 临时替换为 mutex 解决了这个问题。 没有更多时间深入研究细节,但希望这些信息能帮助遇到类似问题的人。
感谢大家的评论!
我在 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 );
}
}