3

私はしばらくの間、次のリークに苦しんでいます。Instrumentsを介して、次のコードブロックに絞り込みました。

- (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]];

recipientNSStringはどこにありますか。

そして、ここに機器からのバックトレースがあります:

  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

windowControllersメソッドでNSMutableArray割り当てられapplicationDidFinishLaunching、解放されdeallocます。

ではNewMessageWindowController、以下を使用して、ウィンドウが閉じようとしていることをアプリデリゲートに通知し、コントローラーを保持する必要がなくなったことを通知します。

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

アプリデリゲートのメソッドは次のようになります。

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

前後の配列をログに記録することは、私が期待する方法です。コントローラはウィンドウが閉じる前にそこにあり、ウィンドウが閉じると削除されます。

窓を閉めると、機器が漏れを拾います。開いている間は、すべてが正常に見えます。期待どおり、DeallocがNewMessageWindowControllerで呼び出されていることに注意してください。リークはコントローラー自体を問題として報告していません。代わりに、リークしているオブジェクトはNSCFStringであり、上記のコードから発生しているだけです。

Build and Analyzeは何も検出していません。また、ウィンドウコントローラー/ウィンドウを作成/表示するコードのブロックでメモリ管理が正常に行われていると確信しています。

奇妙なことに、キーボードを使用してウィンドウを閉じた場合にのみリークが発生します。赤い閉じるボタンをクリックしても、Instrumentsは何も検出しません。

最後に、Instrumentsは、そのコードブロックが責任を負うことを常に示しているわけではありません。そのような場合、Instrumentsで私のコードは参照されていません。すべてAppKitのようです。繰り返しますが、これはキーボードを使用してウィンドウを閉じる場合のみです(cmd-w)。

何か案は?

4

2 に答える 2

0

この場合、Xcode4のInstrumentsのバージョンを使用して、保持/解放イベントを記録するように割り当てインスツルメントを構成します。これは、この特定のコントローラーの場合、保持カウントがゼロにならない理由を示しているはずです。マウスベースのクローズとキーボードベースのクローズでは、異なるコードパスが実行される可能性があることに注意してください。

于 2011-05-25T17:14:54.397 に答える
0

これは、オブジェクトが「破棄」されたときに確実に呼び出されるdeallocを期待できないためです。何らかの理由でキーボードを使用すると、Xをクリックするよりもdeallocがすぐに呼び出される可能性が低くなる可能性があります。

于 2011-05-25T17:15:19.320 に答える