5

バックグラウンド スレッドに入るメソッドを呼び出しています。

[self performSelectorInBackground:@selector(loadViewControllerWithIndex:) withObject:[NSNumber numberWithInt:viewControllerIndex]];

次に、セレクターによって呼び出されるこのメソッドの実装があります。

- (void) loadViewControllerWithIndex:(NSNumber *)indexNumberObj {
    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init];
    NSInteger vcIndex = [indexNumberObj intValue];

    Class c;
    UIViewController *controller = [viewControllers objectAtIndex:vcIndex];

    switch (vcIndex) {
        case 0:
            c = [MyFirstViewController class];
            break;
        case 1:
            c = [MySecondViewController class];
            break;
        default:
            NSLog(@"unknown index for loading view controller: %d", vcIndex); // error
            break;
    }

    if ((NSNull *)controller == [NSNull null]) {
        controller = [[c alloc] initWithNib];
        [viewControllers replaceObjectAtIndex:vcIndex withObject:controller];
        [controller release];
    }

    if (controller.view.superview == nil) {
        UIView *placeholderView = [viewControllerPlaceholderViews objectAtIndex:vcIndex];
        [placeholderView addSubview:controller.view];
    }

    [arPool release];
}

そのスレッド用にそこに自動解放プールを作成しますが、常に次のエラーが発生します。

2009-05-30 12:03:09.910 Demo[1827:3f03] *** _NSAutoreleaseNoPool(): Object 0x523e50 of class NSCFNumber autoreleased with no pool in place - just leaking
Stack: (0x95c83f0f 0x95b90442 0x28d3 0x2d42 0x95b96e0d 0x95b969b4 0x93a00155 0x93a00012)

自動解放プールを削除すると、このようなメッセージが大量に表示されます。また、performSelectorInBackground: の呼び出しの周りに自動解放プールを作成しようとしましたが、それは役に立ちません。

パラメーターが疑わしいのですが、コンパイラーが NSCFNumber について文句を言う理由がわかりません。何か不足していますか?

私のインスタンス変数はすべて「非アトミック」です。それは問題になる可能性がありますか?

更新: メイン スレッドの自動解放プール (おそらく ivar) にいくつかの変数が追加されているのではないかと疑うかもしれませんが、間違った自動解放プール内でその変数を解放しようとしていますか? もしそうなら、どうすればそれを修正できますか?(くそー、このスレッド化は複雑です;))

4

2 に答える 2

7

この理由として最も可能性が高いのは、リークされたオブジェクト (NSNumber) がスレッドの外部から渡されたパラメーターであるためです。したがって、この変数は呼び出しスレッド (およびその自動解放プール) に属します。

スレッド呼び出しの周りの自動解放プールが機能しない理由は、スレッドの作成者 (performSelectorInbackground) がすぐに戻るためです。ほとんどの場合、スレッドがまだ実行されている間に返されます。

セレクターのパラメーターを引数として渡した後、パラメーターを解放することをお勧めします。

于 2009-05-30T10:47:07.187 に答える
3

この理由は、リークされたオブジェクト (NSNumber) がスレッドの外部から渡されたパラメーターであるためであることに同意します。したがって、この変数は呼び出しスレッド (およびその自動解放プール) に属します。

呼び出しスレッドは使用する必要がNSAutoreleasePool あり、次のように保持命令をパラメーターに追加することをお勧めします。

- (void) loadViewControllerWithIndex:(NSNumber *)indexNumberObj {
    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init];
    [indexNumberObj retain];

    ....

    [arPool release];
  }
于 2010-06-12T02:31:28.027 に答える