2

リモートエンドからデータを受信するたびに、AsyncSocket オブジェクトが以下のデリゲートメソッドを呼び出す AsyncSocket を使用しています。

- (void)onSocket:(AsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag;

このメソッド内で、NSData オブジェクトを次のコマンドに渡し、受信したデータの NSString 表現を取得します。

NSString *body = [NSString stringWithCString:[data bytes] length:[data length];

NSString stringWithCString: length: は、渡したバイト配列を保持しますか? NSData *data を保持する必要がありますか? 最後に NSString *body を解放する必要がありますか?

ありがとう。デリゲートメソッドに関してメモリ管理を正しくしたい...

4

4 に答える 4

2

NSString stringWithCString: length: は、渡したバイト配列を保持しますか?

バイト配列を保持することはできません。保持できるのはオブジェクトのみです。

NSData *data を保持する必要がありますか?

いいえ。文字列がデータ (認識していない) またはその内容を保持する方法がないため、文字列はバイトをコピーします。(このメソッドを実装していたらどうするか考えてみてください。これです。)

場合を変えて、バイトの代わりにデータ オブジェクトを渡すとどうなるかを見てみましょう。

文字列がデータを保持している場合、文字列がデータを保持しているため、文字列の下からデータが消えることを心配する必要はありません。保持されない場合、文字列は独自のコピーを作成したか、データをまったく保持していません。

したがって、他のオブジェクトの保持は問題になりません。それらについて心配する必要はありません。誰が何を所有しているかだけを気にし、それに応じて保持するかしないかを考えてください。

最後に NSString *body を解放する必要がありますか?

保存も割り当てもコピーもしませんでした。したがって、あなたはそれを所有していません。いいえ。

オブジェクトの所有権を取得したい場合は、それを保持するか、独自のコピーを作成 (および所有) します。それからあなたはそれを解放します。

于 2009-06-02T20:54:47.353 に答える
1

証明付きの簡単な答え。NSString stringWithCString:encoding: バイト バッファをコピーして文字列を作成します。バッファはあなた次第です。

証拠:

コード:

    const char* hardString = "Hello, World";
    char *buffer = nil;

    buffer = calloc(13, 1);
    bzero(buffer, 13);

    memcpy(buffer, hardString, 12);

    NSString *aString = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];        
    NSLog(@"aString: %@  \t filled buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    bzero(buffer, 13); 
    NSLog(@"aString: %@  \t zeroed buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    free(buffer);
    NSLog(@"aString: %@  \t free'd buffer:(%p)", aString, (void*)buffer);

    buffer = nil;        
    NSLog(@"aString: %@  \t nulled buffer:(%p)", aString, (void*)buffer);

結果:

aString: Hello, World    filled buffer:(0x10010a790) [Hello, World]
aString: Hello, World    zeroed buffer:(0x10010a790) []
aString: Hello, World    free'd buffer:(0x10010a790)
aString: Hello, World    nulled buffer:(0x0)
于 2012-03-27T15:57:22.420 に答える
0

フォルカーは正しいです。stringWithCString:encoding:代わりに使用する必要があります。

Retain/Release はオブジェクトにのみ必要です。C文字列(NSStringとは異なり、オブジェクトではありません)を渡しているため、保持または解放するものは何もありません。

便利なコンストラクターを使用しているため、NSString の保持カウントは 1 ですが、自動解放プールに追加されるため、コード ブロックを離れた後、これは解放されます。それを保持するために alloc メソッドと init メソッドを明示的に使用する必要はありません。つまり、保持カウント 1 で作成されます (ただし、自動解放されます)。保持を呼び出すと、カウントが 2 に増加しますが、しばらくすると、自動解放され、保持カウントが低下します。 1に。

オブジェクトで init、retain、copy、または mutableCopy を呼び出さない場合は、自動解放されると想定でき、明示的に何かを解放する必要はありません。しかし、コード ブロックの外でオブジェクトを保持したい場合は、retain を呼び出し、しばらくしてから解放する必要があります (通常は、オブジェクトが作成されたクラスの dealloc メソッドで)。

于 2009-06-02T12:37:04.503 に答える
0

NSData 配列の内容は新しい NSString オブジェクトに変換/コピーされるため、保持する必要はありません。

返された NSString オブジェクトの保持カウントは 1 ですが、自動解放プールに追加されています。
これは、自動解放プールが破棄されると自動的に解放されることを意味します。AppKit によって作成されたデフォルトの自動解放プールを使用している場合、これは現在のイベント ループ処理の最後に発生します。したがって、この文字列オブジェクトをそのメソッド「onsocket:...」でのみ使用する場合は問題ありません。

メソッドを終了した後も NSString オブジェクトを保持する場合は、
[[NSString alloc] initWithBytes:[...] length:[...] encoding:[. ..]]
この NSString オブジェクトの保持カウントも 1 になりますが、不要になったら明示的に解放する必要があります。

ところで。[NSString stringWithCString:length:] は OSX 10.4 以降非推奨です

于 2009-06-02T12:23:58.167 に答える