最令人费解的C ++堆分配错误

时间:2015-08-28 17:29:12

标签: c++ multithreading mutex heap-memory stack-memory

我无法发布源代码,但我可以在概念层面上解释它的一部分,并希望我能帮助理解我的解决方案的工作原理。

我有一个有3个线程的应用程序:A,B和C(主线程)。

线程B有一个Foo对象列表。

每个Foo对象包含1个Mutex对象,它是递归互斥体的包装器,以及一组用于以同步方式设置和获取各种属性的方法,使用Mutex和2个方法用于设置和获得markedForDelete属性。

线程B所做的就是使用迭代器遍历所述列表,并删除标记为删除的Foo对象,否则执行其他指令。它是使用与此类似的基本代码来破坏Foo对象的唯一线程:

while (running)
{
    fooListLock->Lock();
    for (vector<Foo*>::iterator it = fooList.begin(); it)
    {
        if (it->isMarkedForDelete())
        {
            it = fooList.erase(it);
        }
        else
        {
            it->execute();
        }
    }
    fooListLock->Unlock();
    sleep (sleepVariable);
}

线程A和C将创建Foo对象并将其添加到列表中,它们也可以将它们标记为要删除,并使用其他互斥锁以同步方式完成。

线程C偶尔会被关闭,之后总是会以一种受控的方式重新启动,永远不会在内存分配/释放期间,并且总是会释放锁定的互斥锁。

问题在于,当Foo的Mutex在堆内存中分配时(通过new运算符),应用程序将达到死锁状态,其中线程C想要访问由线程A锁定的资源,并且前者想要访问由线程B和线程B锁定的资源被Foo的互斥锁阻止,该互斥锁被锁定但没有所有者。使用GDB我发现Mutex的pthread_mutex_t所有者值为0或负数,不对应于任何线程的id。死锁的阻塞结束发生在线程B中的这段代码:if (it->isMarkedForDelete())

我非常直观的解决方案是在堆栈上分配Foo的Mutex,它无需任何其他修改即可运行!应用程序不会以这种方式达到死锁状态。

使用g ++ 4.8设置O2标志进行编译。

我知道继续下去并不多,但是有人可以帮我理解为什么我的解决方案有效吗?

1 个答案:

答案 0 :(得分:1)

我当然相信,它与堆错误无关。最有可能的是,您没有正确初始化互斥锁。你在调用pthread_mutex_initialize吗?