2016-06-08 48 views
2

我有一段代码,其中我有类似free()调用:程序随机崩溃由于在多个线程中

int *mem_ptr; 
. 
. 
if(mem_ptr) 
{ 
    free(mem_ptr); 
} 
. 
. 

该应用程序是多线程的。有时,一个线程会通过if检查,然后free()发生上下文切换,另一个线程也会通过if检查并执行free()。现在,当控制回到第一个线程时,它在free()处崩溃,给出错误Abort message: 'invalid address or address of corrupt block 0x40735cb0 passed to dlfree'

除了互斥,有没有更好的方式来处理这种情况

PS:我的工作在Android原生料在C++中,这一段代码是onTransact()调用中。

+2

你不能使用shared_ptr的?如果不是,使用原子增量和减量来实现一个ref-counting机制将是值得的。 – Arunmu

+2

Arunmu的权利 - 你的逻辑内在地被打破,不仅仅是因为潜在的多重释放,还因为一个线程可能释放指向内存,而另一个线程继续使用它(尚未使它成为“if”)。 Jeegar关于使'free(mem_ptr)'原子的答案不足以获得可靠的工作代码。 –

+0

确保mem是通过malloc分配的 – David

回答

0

两件事情:

1)free操作应是原子的。因此,请使用任何机制,如互斥锁,信号量等。

2)在free()调用后,明确地将您的指针更新为NULL。所以在第二个线程中,它不会放弃if()

请注意:free()调用内存后不会将NULL指定给您的指针。

+0

这就是关键所在。即使我分配NULL,两个线程都已输入检查....所以在某些情况下它不会起作用。它取决于上下文切换发生的位置。 Mutex绝对是解决方案。这就是我在我的问题中写的。 –

+0

@InsaneCoder,no,'NULL' from'NULL'指针工作正常。因此,如果线程内有少量线程进入,则没有问题。但'free'和将指针设置为NULL必须是原子的。 – Arkady

1

如果两个或多个线程试图释放/删除相同的内存,那么代码和设计都会中断。虽然线程同步原语会有所帮助,但我也不会使用它们。应该只有一个线程释放内存。理想情况下应该是分配内存的人。如果不同,如果是跨线程消息传递,仍然只有一个目标线程应该删除内存。

这就像说一个线程打开一个文件,任何线程都会关闭它。它看起来不太好。文件的关闭应该由单线程完成,而不是由多个线程在争用中完成。

0

因为freeNULL效果很好,什么都不做,使用:

int *mem_ptr(NULL); 
. 
. 
if(mem_ptr) 
{ 
    //any multithreaded lock guard have to be here 
    free(mem_ptr); 
    mem_ptr = NULL; 
} 

所以,只有你有关心,事情是,运营free和设置指针NULL必须是原子的。

这意味着停止所有其他线程执行这些操作,直到没有完成,这意味着使用核心同步对象。

+0

锁的位置应该在_if之前。建议的代码是双重检查锁定模式的变体。 – MSalters

+0

但是如果第二个线程会进入'if',那么会出现什么问题,然后等待第一个线程释放内存并将指针设置为NULL,然后只需从NULL调用'free',并将指针重写为'NULL'? – Arkady

+0

问题是在第二个线程上调用'free(mem_ptr)'没有调用'free(NULL)',它调用'free(mem_ptr)'。当你没有适当地保护对'mem_ptr'的访问时,在另一个线程上将'mem_ptr'设置为'NULL'的事实是无关紧要的。因为你对if(mem_ptr)进行了无保护的检查,所以编译器可能会认为没有其他线程改变它。把锁放在正确的位置告诉编译器:mem_ptr是共享的,其他线程可以写入它,因此它只能放在该锁定范围内的寄存器中。 – MSalters

0

您可以将指针指向NULL,如其他答案中所述......但这仍不能保证成功。两个线程都可以通过并且一个接一个地调用free(),然后在这个....之后都分配为NULL,但是由于程序可能已经崩溃,所以太晚了。

这里需要使用线程同步机制,就像一个互斥体:

std::mutex mtx;   // declare mutex for critical section 
    : 
    : 
mtx.lock(); // only one thread will get inside here... 
if(mem_ptr) 
{ 
    //any multithreaded lock guard have to be here 
    free(mem_ptr); 
    mem_ptr = NULL; 
} 
mtx.unlock(); // release the mutex...