2010-12-06 55 views
9

如果你曾經問我如何調試釋放/ Objective-C中的alloc的問題,你會在這些環境設置就可以幫助追蹤問題了下來:瞭解一個malloc_history轉儲

  • NSZombieEnabled - 保持發佈後各地下流,這樣你就可以得到指針等
  • MallocStackLogging - 保留對象歷史以備日後參考
  • NSDebugEnabled

您在「可執行文件」(可在組樹中找到)信息的「參數」選項卡的「環境」部分中將所有這些設置爲YES


所以,即時得到此控制檯輸出

MyApp的[:40B] - [CALayer的 retainCount]:消息發送到 釋放的實例0x4dbb170

然後打開終端,而調試器已轉發第Ë休息和類型:

malloc_history 4413 0x4dbb170

然後,我得到一個大的文本轉儲,而據我瞭解的重要一點是:

ALLOC 0x4dbb160-0x4dbb171 [size=18]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[PDFDocument loadPDFDocumentWithPath:andTitle:] | 
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction | 
ListDictionaryObjects(char const*, 
CGPDFObject*, void*) | NSLog | NSLogv 
| _CFLogvEx | __CFLogCString | 
asl_send | _asl_send_level_message | 
asl_set_query | strdup | malloc | 
malloc_zone_malloc 
FREE 0x4dbb160-0x4dbb171 [size=18]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[PDFDocument loadPDFDocumentWithPath:andTitle:] | 
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction | 
ListDictionaryObjects(char const*, 
CGPDFObject*, void*) | NSLog | NSLogv 
| _CFLogvEx | __CFLogCString | 
asl_send | _asl_send_level_message | 
asl_free | free 
ALLOC 0x4dbb170-0x4dbb19f [size=48]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[ScrollViewWithPagingViewController init] | -[UIView init] | 
-[UIScrollView initWithFrame:] | -[UIView initWithFrame:] | UIViewCommonInitWithFrame | -[UIView 
_createLayerWithFrame:] | +[NSObject(NSObject) alloc] | +[NSObject(NSObject) allocWithZone:] | class_createInstance | 
_internal_class_createInstanceFromZone | calloc | malloc_zone_calloc 

什麼,我不明白,雖然是,如果它的歷史被ALLOC,免費,ALLOC那麼爲什麼錯誤表明,它被釋放(淨+1 ALLOC)?

還是我對轉儲的理解錯誤?


EDIT(勁跑=不同的對象指針):

的殭屍檢測儀器有:

爲什麼和怎麼樣,不從1擋計數跳轉到-1?

望着殭屍的回溯,貌似保留計數被稱爲是:通過release_root_if_unused

石英


編輯:解決 - 我被去除超視圖,然後釋放它。通過發佈它來修復。

回答

2

@Kay是正確的; malloc歷史在指定的地址顯示兩個分配;一個已經分配和釋放,另一個仍在發揮作用。

您需要的是已撥出CALayer的電話retainCount的回撥。因爲你已經啓用了殭屍檢測,所以在其他的內存調試中,可能會出現這種情況,因爲釋放根本就不是&。

將malloc歷史與殭屍檢測混合使用會顯着改變運行時行爲。

我建議運行在儀器中的殭屍檢測。希望能夠指出確切的問題。

如果沒有,那麼當殭屍被髮送消息時,您可以設置一個斷點。設置斷點並查看停止的位置。


OK - 所以,CoreAnimation使用保留供內部使用計數(系統架構可以過關了這一點,雖然脆弱它是)。

我認爲-1是紅鯡魚;殭屍可能返回0xFF .... FFFF作爲保留計數,並且這在儀器中呈現爲-1。

下一個最好的猜測;由於這發生在計時器中,因此過度釋放可能在動畫過程中發生。 CoreAnimation圖層應該正確處理這個問題。在您的代碼中存在視圖或動畫圖層容器的過度釋放,導致圖層過早消失。

您是否嘗試過「構建和分析」?這可能會導致某個地方的視線管理不善。

在任何情況下,作爲實驗,請嘗試保留您的視圖一個額外的時間,並查看是否導致此問題停止。如果是這樣,那至少是一條線索。

(或者它可能是系統框架中的錯誤......也許......但值得懷疑。)

最後,誰在打電話retainCount?!?!?在CoreAnimation的情況下,retainCount可能在內部用作實現細節。

如果是你的代碼,那麼殭屍呼叫的位置應該是非常明顯的。

0

我不是專家,但如果你把塊3來看看第一行:

ALLOC 0x4dbb170 -0x4dbb19f [大小= ]:

雖然在另外兩個輸出中,0x4dbb160-0x4dbb171的大小爲18的內存塊被分配並釋放。我假設舊對象已被釋放,並且存在此內存地址處的新對象。因此,0x ... b160的舊實例不再有效。

+0

我認爲這個尺寸可能是一個指標。對象的id是開始地址,因此在塊3中分配的對象是引起我的問​​題的對象(因爲它的起始地址是在控制檯中報告的對象)。 – 2010-12-06 13:43:37

+0

我不明白的是它在這裏清楚地表明它被分配。但錯誤表明它已被釋放... – 2010-12-06 13:44:41