2

マルチスレッドのiPhoneアプリケーションでメモリ管理に関連する質問があります。main-UIスレッドとは別のスレッドで呼び出されるこのメソッドがあるとしましょう。

- (BOOL)fetchAtIndex:(NSUInteger)index
{
    NSURL *theURL = [NSURL URLWithString:[queryURLs objectAtIndex:index]];
    // Pay attention to this line:
    NSData *theData = [[NetworkHelper fetchFromNetwork:theURL] retain];

    // Some code here...

    // Now what should I do before returning result?
    //[theData release]; ??
    //[theData autorelease]; ??
    return YES;
}

ご覧のとおりNSData、ネットワーク運用から戻ってきたものを保持しています。問題は、メソッドの最後にリリース(または自動リリース)しないのはなぜですか?私がそれを機能させる唯一の方法はretain、最初は使用することであり、その後は何も使用しません。他の組み合わせを使用すると(何もしない; retainthenreleaseまたは)、スレッドを解放するautoreleaseとプログラムがクラッシュします。私は何が欠けていますか?EXC_BAD_ACCESSNSAutoreleasePool

参考までに、スレッドのメインコードは次のとおりです。

- (void)threadedDataFetching;
{
    // Create an autorelease pool for this thread
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Reload data in separate thread
    [self fetchAtIndex:0];

    // Signal the main thread that fetching is finished
    [self performSelectorOnMainThread:@selector(finishedFetchingAll) withObject:nil waitUntilDone:NO];

    // Release all objects in the autorelease pool
    [pool release]; // This line causes EXC_BAD_ACCESS
}

ご協力いただきありがとうございます!

4

3 に答える 3

3

自分で保持していないものを解放してはなりません(名前に:、、、またはを含むメソッドを使用して、または暗黙retain的に使用します)。initnewcopy

からの結果を保持する場合はfetchFromNetwork、それを解放する必要があります。両方ともrelease機能autoreleaseするはずです(後にオブジェクトに触れないでください。releaseフィールド/変数をnilafterに設定するのが最も安全ですrelease)。

データを保持していない場合は、保持する必要もありません。[NetworkHelper fetchFromNetwork]自動解放されたオブジェクトを返す必要があります。の本体は次のfetchFromNetworkようになります。

NSData *data = [[NSData alloc] init];
// stuff happens
return [data autorelease];

また

NSData *data = [otherObject dataFromOtherObject];
// stuff happens
return data; // don't (auto)release, since you haven't retained

疑わしい場合は、リーク側でエラーを起こし、「リーク」機器またはLLVMチェッカーを介してアプリケーションを実行します。

于 2009-07-27T20:40:15.367 に答える
0

別のスレッドを使用しているという事実は、ここでは関係がない可能性があります。メモリ管理は同じであり、これがメインスレッドであるかのように、NSDataの保持/解放のバランスをとる必要があります。自動解放プールを空にするときにクラッシュしているという事実は、おそらくここに示していないデータで何かをしたことを示唆しています(示されているコードはあまり役に立たないので明らかです)。他の誰かにそれを保持することを要求しているデータで何をしていますか?

于 2009-07-27T20:52:35.670 に答える
0

他の人が指摘しているように、このインスタンスでマルチスレッド化されていることは実際には関係ありません。Appleが作成したObjectiveCメモリ管理ガイドラインを読む価値があります。

大まかに言えば、自分で明示的に[[Foo alloc] init]するオブジェクトはすべて、クリーンアップの責任を負う必要があります。メソッドからこの値を返す場合は、それも自動解放する必要があります。

initWithで始まらない呼び出し元から取得したオブジェクト([Foo emptyFoo]など)は、リソースを所有する(つまり、自動解放する)のは呼び出し元の責任です。

オブジェクトが渡され、それをメソッド呼び出しの外に保持したい場合(つまり、インスタンスフィールドに保存したい場合)、オブジェクトを保持する必要があります。完了したら、通常はデストラクタでリリースします。Objective Cのプロパティを使用している場合、それを@retainとして定義すると、この動作が自動的に開始されます。デストラクタでは、プロパティをnilに設定するだけです。

于 2009-07-28T08:55:16.603 に答える