2016-06-08 82 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...