【发布时间】:2016-03-22 14:53:04
【问题描述】:
我的代码在 QNX 上定期崩溃。它因错误而崩溃
错误读取变量:无法访问地址
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 或类似的错误吗?
有什么想法可以找到问题吗?
【问题讨论】:
-
你在使用 GCC 吗?大胆猜测:QNX Pthreads 实现仅支持将 PTHREAD_ONCE_INIT 用于静态对象,而
std::once_flag类型中的数据成员的使用不起作用。如果您使用全局std::once_flag而不是m_once_flag,会有所不同吗? (我意识到这意味着您只能执行一次初始化,而不是每个对象一次,但它可能有助于追踪问题)。 -
@Jonathan,它是
mutable,所以它必须是一个非静态数据成员(“m_”前缀也强烈建议!) -
为什么不将变量仅在需要存储时才存储在地图中?没看懂
-
我在这里可能已经过时了,但我上次检查 QNX 支持的 GCC 是 4.7 版。 C++11 支持有点不稳定。
-
使用低级 POSIX pthread_once 能解决问题吗?
标签: c++ multithreading c++11 lazy-initialization qnx