经过同事的多次调试,终于解决了这个问题。
执行摘要
pthread_mutex_init () 在 55-65 后抛出异常增强::互斥体构造函数调用,因为具有 boost::mutex 作为成员变量的应用程序级派生类对象未完全析构,因为基类析构函数是非虚拟的。这导致 boost::mutex-s 的数量不断增加,直到抛出互斥异常。当派生类的析构函数被正确调用时,将不再引发互斥异常。
沿途收集的相关/有趣的事实
(1) 一个早期的理论被提出,系统中存在太多的互斥体,并且应用程序超出了允许的同步对象最大数量的一些未知限制(尽管QNX文档明确指出此类对象的数量是无限的)。为了测试这一点,我们修改了增强::互斥体班级来自:
class mutex
{
private:
. . .
public:
mutex()
{
. . .
}
~mutex()
{
. . .
}
}
to:
class mutex
{
private:
static int _nCount;
public:
mutex()
{
++_nCount;
. . .
}
~mutex()
{
. . .
--_nCount;
}
static int getCount ()
{
return _nCount;
}
. . .
}
请注意,对 _nCount 变量的访问不是同步的(为此我们需要一个互斥对象!),但调用调试boost::mutex::getCount()应用程序中的函数让我们确信,异常发生时互斥量的数量很少(平均 55-65 个活动互斥量)。
这种通过添加静态访问函数来监视最低级别的对象(例如 Boost 中的互斥体)的技术是调试棘手问题时需要考虑的好工具。
(2) 我们偶尔会收到 ENOMEM 异常,表明存在内存问题(“系统无法分配创建互斥锁所需的资源").
(3) FreeBSD 网站三个月前发布的内容 http://lists.freebsd.org/pipermail/freebsd-threads/2013-May/005422.html与我们的症状非常相似:
我遇到了似乎无法解决的麻烦。我的节目
重复地创建和销毁互斥体(并且,显然,将它们用于
之间)。在创建第 60 个锁时,我总是得到 ENOMEM。我有
空闲内存,很多。所有锁都可以正确释放。
不幸的是,这条线索并没有为我们指明建设性的方向。
(4) 当仔细研究应用程序的代码时,发现派生对象的基类析构函数是非虚拟的,从而泄漏了一些内存,从而取得了突破。将基类析构函数设为虚拟修复了内存泄漏并解决了互斥异常。
(5) 即使在将基类的析构函数设为虚拟之后,我们发现在使用 QNX® Momentics 工具套件编译 Blackberry 10 时,派生类的析构函数并未被调用。我们通过指定基础来“解决”这个问题和导出的析构函数作为虚拟的。然后派生的析构函数才被调用。这可能表明 QNX 编译器的 C++ 规范实现中存在错误,该规范明确指出虚拟性传播到派生类 (工作草案,编程语言 C++ 标准 (2012),第 250 页,脚注 9 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf).
编辑:参见这个堆栈溢出帖子 https://stackoverflow.com/questions/35132860/my-qnx-bb10-c-application-crashes-a-simple-c-object-seems-to-be-corrupted/35132861#35132861QNX 在虚拟析构函数方面失败的另一个例子。