2011-05-25 58 views
3

我一直在努力與下面的泄漏一段時間了。我已經收窄,通過儀器對下面的代碼塊:內存泄漏NSWindowController的showWindow:

- (NewMessageWindowController *)showNewMessageWindowWithRecipients:(NSArray *)recipients { 

    NewMessageWindowController * newMessageWindowController = [[NewMessageWindowController alloc] init]; 
    [newMessageWindowController showWindow:self]; // 100% on this line. 
    [newMessageWindowController.toField setStringValue:[recipients componentsJoinedByString:@","]]; 
    [newMessageWindowController.messageView becomeFirstResponder]; 
    [windowControllers addObject:newMessageWindowController]; 
    [newMessageWindowController release]; 

    return newMessageWindowController; 
} 

塊被稱爲像這樣:

[AppDelegate showNewMessageWindowWithRecipients:[NSArray arrayWithObject:recipient]]; 

哪裏recipient只是一個NSString。

這裏是從儀器回溯:

30 Friendz start 
    29 AppKit NSApplicationMain 
    28 AppKit -[NSApplication run] 
    27 AppKit -[NSApplication sendEvent:] 
    26 AppKit -[NSWindow sendEvent:] 
    25 AppKit -[NSWindow keyDown:] 
    24 AppKit forwardMethod 
    23 Friendz -[FriendzAppDelegate showNewMessageWindowWithRecipients:] /Path/To/FriendzAppDelegate.m:226 
    22 AppKit -[NSWindowController showWindow:] 
    21 AppKit -[NSWindow makeKeyAndOrderFront:] 
    20 AppKit -[NSWindow _makeKeyRegardlessOfVisibility] 
    19 AppKit -[NSWindow _changeKeyAndMainLimitedOK:] 
    18 AppKit -[NSWindow becomeKeyWindow] 
    17 AppKit _NXResetCursorState 
    16 AppKit +[NSEvent _discardCursorEventsForWindowNumber:criteria:] 
    15 HIToolbox FlushSpecificEventsFromQueue 
    14 HIToolbox PullEventsFromWindowServer 
    13 HIToolbox PullEventsFromWindowServerOnConnection(unsigned int, unsigned char) 
    12 HIToolbox ConvertPlatformEventRecordAndPostWithOptions(__CGEvent*, _CGSEventRecord const*, short, unsigned char, unsigned char) 
    11 HIToolbox PostEventToQueueInternal 
    10 HIToolbox _NotifyEventLoopObservers 
    9 HIToolbox KeyEventPostedObserver 
    8 HIToolbox TSMProcessRawKeyCode 
    7 HIToolbox TSMTranslateKeyEvent 
    6 HIToolbox GetDataFromUCHRForEvent 
    5 HIToolbox ConvertEventUniCharsToCharCodes 
    4 HIToolbox utGetInputSourceScriptInfo 
    3 CoreFoundation CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes 
    2 CoreFoundation CFStringCreateWithCStringNoCopy 
    1 CoreFoundation __CFStringCreateImmutableFunnel3 
    0 CoreFoundation _CFRuntimeCreateInstance 

windowControllersNSMutableArray分配/ init'ed在applicationDidFinishLaunching並在dealloc方法釋放。

NewMessageWindowController,我用下面的通知應用程序代理,窗口即將關閉,而且也沒有必要保留控制器更多:

- (void)windowWillClose:(NSNotification *)notification { 
    [AppDelegate windowControllerDidFinish:self]; 
} 

應用程序委託的方法是這樣的:

- (void)windowControllerDidFinish:(NSWindowController *)controller { 
    [windowControllers removeObject:controller]; 
} 

記錄陣列之前和之後是我如何期待它。窗戶關閉前,控制器位於那裏,當窗戶關閉時,控制器將被移除。

當我關閉窗戶時,儀器會檢測到泄漏。雖然它是開放的,但一切似乎都很好。值得注意的是,按預期在NewMessageWindowController中調用dealloc。泄漏不是將控制器本身報告爲問題,而是泄漏的對象是NSCFString,它只是源自上面的代碼。

構建和分析不會挑選任何東西,我很確定我的內存管理在創建/顯示窗口控制器/窗口的代碼塊上很好。

奇怪的是,如果我使用鍵盤關閉窗口,只會有泄漏。如果我點擊紅色的關閉按鈕,樂器不會選擇任何東西。

最後,Instruments並不總是顯示該代碼塊負責。在這些情況下,我的代碼沒有在樂器中引用 - 它似乎都是AppKit。再說一遍,只有當我用鍵盤關閉一個窗口(cmd-w)時纔是如此。

任何想法?

回答

0

我在這種情況下會做的是,使用Xcode4中的Instruments版本配置分配工具以記錄保留/釋放事件。這應該告訴你,對於這個特定的控制器,爲什麼它的保留計數不會爲零。請注意,可能會爲基於鼠標和基於鍵盤的關閉執行不同的代碼路徑。

+0

當使用鍵盤或鼠標時,Dealloc確實在NSWindowController中調用。 – 2011-05-25 17:39:47

+0

是儀器說,NewMessageWindowController是對象泄漏?如果是這種情況,並且您看到對象正在交易,這意味着您有一個錯誤的泄漏。稍等片刻後,嘗試重新運行泄漏掃描;泄漏可能會消失。如果對象明顯被釋放,我不會擔心這個泄漏。 – 2011-05-25 21:54:50

+0

樂器正在顯示一個NSCFString作爲泄漏對象,它只是源自showWindow調用(或者Instruments所說的)。 – 2011-05-25 22:43:16

0

這是因爲當一個對象被「銷燬」時,你不能指望dealloc被可靠地調用 - 這可能是因爲某種原因使用鍵盤不太可能導致直接調用dealloc而不是點擊X?

+0

我看到dealloc調用NewMessageWindowController使用鍵盤或鼠標關閉它的窗口。 – 2011-05-25 17:41:43