2012-08-08 53 views
0

我一直在使用Instruments應用程序檢查我的應用程序泄漏。在某些情況下,HUD Panel中的表格視圖每秒更新一次。除了每秒(reloadData),_NSArrayl對象的數量增加一個,它都工作正常。如果我將我的數據源更改爲僅返回(@「」); (他們都是文本單元格),問題依然存在(不變)。如果我刪除我周圍所有的代碼只是:NSTableView reloadData泄漏內存

[myTableView reloadData]; 

- (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)column row:(int)rowIndex { 
    return(@""); 
} 

(甚至返回nil)

問題仍然存在。註釋掉[myTableView reloadData]並且問題消失。 每個塊是_NSarrayl並且尺寸是32個字節,而細節:

0 libsystem_c.dylib calloc 
    1 libobjc.A.dylib class_createInstance 
    2 CoreFoundation __CFAllocateObject2 
    3 CoreFoundation +[__NSArrayI __new::] 
    4 CoreFoundation -[__NSPlaceholderArray initWithObjects:count:] 
    5 CoreFoundation +[NSArray arrayWithObjects:] 
    6 AppKit -[NSWindow _runLoopModesForInvalidCursorRectsObserver] 
    7 AppKit __-[NSWindow _postInvalidCursorRects]_block_invoke_1 
    8 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 
    9 CoreFoundation __CFRunLoopDoObservers 
    10 CoreFoundation __CFRunLoopRun 
    11 CoreFoundation CFRunLoopRunSpecific 
    12 HIToolbox RunCurrentEventLoopInMode 
    13 HIToolbox ReceiveNextEventCommon 
    14 HIToolbox BlockUntilNextEventMatchingListInMode 
    15 AppKit _DPSNextEvent 
    16 AppKit -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] 
    17 AppKit -[NSApplication run] 
    18 AppKit NSApplicationMain 

我曾經在歷史上注意到這些對象有一個自動釋放條目,如果它已經被自動釋放我不知道(保留計數仍然是1)。但5分鐘後,沒有任何東西釋放它們,所以也許autorelease池沒有被釋放。我不創建任何autorelease池(並且不釋放任何),留下應用程序框架。我應該使用autorelease池做些什麼嗎?

# Address Category Event Type RefCt Timestamp Size Responsible Library Responsible Caller 
0 0x100669cf0 __NSArrayI Malloc 1 00:01.342.634 32 AppKit -[NSWindow _runLoopModesForInvalidCursorRectsObserver] 
1 0x100669cf0 __NSArrayI Autorelease <null> 00:01.342.636 0 AppKit -[NSWindow _runLoopModesForInvalidCursorRectsObserver] 

任何關於我可能會做錯的建議將非常感激。

請注意,1秒更新的情況不是應用程序的「正常情況」,但可能發生,然後應用程序設計時間過長;即不是應用程序你的運行,退出,再次運行,退出等。

他們不被檢測爲「泄漏」,但分配計數不斷增加,所以我認爲他們是實踐中的泄漏(或某事正在錯誤)

我沒有使用ARC而不是「垃圾收集」 - 只是保留/發佈系統,我傾向於使用retain/release,我自己的代碼偶爾會使用autorelease,無處可用此代碼。

附加信息:我一直在坐着看數量的增加,只使用Instruments應用程序(tableview在總是可見的HUD中)。但是,如果我將鼠標移到「泄漏」的桌面視圖上 - 計數可以回到合理的程度。將包含桌面視圖的HUD窗口稍稍移動一下,計數就會降低,等等。這似乎是缺少允許這種情況發生的用戶活動。我仍然難過,但認爲這個新的觀察可能有助於想法(或者如果有人試圖重現它)。

回答

0

代碼本身不泄漏。但是可能發生的是外部自動釋放池不會被耗盡。在AppKit中這是一件棘手的事情:AppKit運行循環會自動添加一個自動釋放池,但只有當它接收到事件(即移動鼠標)時纔會消耗它。

您可以通過激活應用程序並移動鼠標再次嘗試泄漏來確認。

這意味着,一般來說,將自己的自動釋放池添加到自定義非事件驅動的回調中是一個不錯的主意。一些基本的基礎機制已經爲你做了這些(例如NSTimer在射擊之前爲你創建一個池並將其排空),但並不是所有的東西都會爲你做。

在這種特殊情況下,看來你沒有對特定的回調這麼多控制:

1)考慮運行泄漏

2之前瘙癢你的應用程序)可能提交Bug來蘋果

+0

對不起 - 我搞砸了,併發布了一個後續問題作爲答案出現在您的答案上方。基本上,按照你的建議,我嘗試了虛擬賽事......工作......不確定......看到上面的細節。非常感謝 – 2012-08-09 09:30:49

0

更新和後續的問題(對不起)** 按照你的建議,我已經添加下面的[myTableView reloadData]有點張貼假/無害消息到應用程序(看起來比直接發送到有關窗口更安全)。

NSEvent *dummyEvent=[NSEvent mouseEventWithType:NSMouseMoved location:NSMakePoint(0.0,0.0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil eventNumber:0 clickCount:0 pressure:0.0]; 
[NSApp postEvent:dummyEvent atStart:FALSE]; 

我的想法是,添加的東西,將發生後的表視圖是Cone一切(基本上在事件隊列爲空。這將類似於用戶在做什麼。這似乎在工作迄今爲不斷增加的分配計數不再增加(如預期的那樣移動了一點,但基本穩定)

但是,我沒有做過多的事件,擔心我的「dummyEvent」可能不會是無害的,也可能會導致問題在未來有沒有更好的方法來實現這一點,或者是否有更好的事件(或參數),我應該使用?

我也嘗試

NSEvent *dummyEvent=[NSEvent otherEventWithType:NSApplicationDefined location:NSMakePoint(0.0,0.0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:(short)(0) data1:0 data2:0]; 

但我在這個知己少,因爲我沒有自定義事件處理程序,並不能確定它可能最終向上。此外,我還第一次遇到了這種變體的地址衝突 - 但我想知道這是否是其他事情,因爲它沒有再次發生。只要沒有任何參數會導致崩潰/斷言失敗或類似情況,我就可以看到虛擬鼠標移動是如何無害的。

+0

如果您知道在應用程序處於後臺時可能會觸發回調,並且您無法使用自己的自動釋放池,那麼確實應該這樣做:剔除AppKit的事件循環。而你的第二個猜測是正確的(不要在這裏混淆鼠標事件)。 – Julien 2012-08-09 16:32:42

+0

非常感謝您對此的建議和幫助。非常感謝。第二個選項是(NSApplicationDefind)。 TableView更新從計時器事件開始;定時器調用對象方法,調用一些其他東西,然後調用tableview reloadData。因此,從您所說的以及Instruments顯示的內容可以看出,顯示更新與定時器事件處理程序或至少在定時器事件自動釋放池之外是異步的。 – 2012-08-09 22:56:37