2014-03-30 91 views
0

從我Note類對象創建的對象是通過保持一個指針列表存儲在名爲m_noteList刪除與「新」

QSharedPointer<Note> note(new Note(this)); 
m_noteList << note; 

QList< QSharedPointer<Note> > m_noteList; 

我通過創建一個類的對象

刪除的推移(獲得正確的指數idx後物色對象):

delete m_noteList[idx].data(); 
在QtCreator(調試模式)

HEAP[MyApp.exe]: 
HEAP: Free Heap block 024FC240 modified at 02500330 after it was freed 

而且dissambler

錯誤消息:

0x777349ab <+0x0000>   cmpb $0x0,0x2(%eax) 
0x777349af <+0x0000>   je  0x777349c6 
0x777349b1 <+0x0000>   movb $0x1,0x7774d640 
0x777349b8 <+0x0000>   mov %ecx,0x7774d644 
0x777349be <+0x0000>   int3 
0x777349bf <+0x0000>   movb $0x0,0x7774d640 //<-- Here is a stop mark 
0x777349c6 <+0x0000>   ret 
0x777349c7 <+0x0000>   nop 
... 

我也試過這樣:

m_noteList.removeAt(idx); 

這也不起作用。由操作系統發出SIGSEGV信號停止的過程(分段故障)

所以,我真的不知道我做錯了,以及如何避開它

我的解決方案是非常髒:設定某種的deleted的-tag到我的對象,但我需要在所有其他功能來檢查這個忽略的對象......

編輯:

我意識到一兩件事:如果我刪除一個音符(與removeAt()),它是刪除(我通過觀看控制檯打印輸出看到它),但它的GUI不會消失。然後,如果我再次單擊該對象的特定按鈕以刪除該註釋,則應用程序會崩潰(因爲它不再存在,但只有gui)。但是如果我之前寫這個deleteLater,在刪除它之後,gui也會消失,一切看起來都很好。 有人可以解釋一下,爲什麼?

m_noteList.at(idx)->deleteLater(); 
m_noteList.removeAt(idx); 
+4

你不應該'刪除'QSharedPointer管理的資源。 – juanchopanza

+0

那麼我應該如何刪除它,或者我可以創建一個'QList '沒有'QSharedPointer'?不知道我是否真的需要它。 – user2366975

+4

一旦沒有處理相同資源的共享指針,刪除就會自動發生。這是共享指針的一點(沒有雙關語意思)。 – juanchopanza

回答

0

給定一個QList<QSharedPointer<Note>> m_noteList

Note對象的刪除是通過m_noteList.removeAt(idx)實現,假設有指針的沒有其他現存的副本。你只需簡單地將最後的共享指針去掉給定的音符,就是這樣。在共享指針的數據上調用delete始終是錯誤

我不能用removeAt重現您的問題 - 只有在您注意到delete時纔會發生,您不應該這樣做。

+0

那麼,我認爲,從技術上講,刪除指針兩次被認爲是*未定義的行爲*。 – Shoe

+1

@Jefffrey或者,用簡單的語言,錯誤:)人們經常感到困惑,因爲他們不認識到未定義和實現定義的行爲之間的所有重要區別。一個錯誤簡潔並且重點:) –

+0

在這種情況下,標準沒有對錯誤進行任何說明。由於未定義的行爲,根據標準,任何事情都可能發生。即使你被獨角獸殺死了。所以,是的,不要做不確定的行爲。 :) – Shoe

2

你混合了內存管理策略:

  1. QObject親子內存管理:當父QObject被刪除,它會自動刪除所有的孩子QObjects。解釋here。刪除對象是自動完成的,所以不需要顯式刪除。

  2. QSharedPointer內存管理:當刪除引用某個對象的最後一個QSharedPointer時,該對象被刪除。解釋here。該對象被自動刪除,因此不需要顯式刪除。

  3. 「手動」內存管理:new對象和delete對象在正確的時間。在C++標準中解釋。該對象必須手動刪除。

您應該只選擇其中之一,以確保不會雙重刪除對象。我建議在#1和#2之間進行選擇,具體取決於您打算如何使用這些對象。如果您打算通過「父母」共享對象,請使用#2,否則使用#1。