10

次のようなObjective-Cコードがあります。

- (NSString *)copyData:(NSData *)data
{
    NSString *path = [[[self outputDirectory] stringByAppendingPathComponent:@"archive"] stringByAppendingPathExtension:@"zip"];
    NSLog(@"Copying data to %@", path);
    [data writeToFile:path atomically:NO];
    return path;
}

コードは、次のような初期化子から呼び出されます。

- (id)initWithData:(NSData *)data
{
    if ((self = [super init]) != nil) {
        NSString *path = [self copyData:data];        // Line 41 (referenced in warning, shown below)
        return [self initWithContentsOfFile:path];
    }
    return self;
}

clang static Analyzerを実行すると、path変数に対して次の警告が表示されます。

41行目に割り当てられ、「パス」に格納されたオブジェクトの潜在的なリーク

+0の保持カウントを持つオブジェクトは、+ 1(所有)の保持カウントが期待される呼び出し元に返されます

よくわかりません。私の理解ではstringByAppendingPathComponent、自動解放された文字列を返す必要があるため、正味保持カウントは0である必要があります(明らかに、保持したくありません)。

私はcopyData:以下を返すように変更しようとしましたが、警告を取り除くことができませんでした:

return [[path retain] autorelease];

では、この警告はどうなるのでしょうか。

4

5 に答える 5

15

プレフィックスが付いたメソッドに気づき、copyCocoaの命名規則に従っていると見なされるため、呼び出し元が所有するものを返す必要があるものとしてフラグを立てているだけだと思います。

もちろん、あなたの場合はファイルなどを参照しているので、無視できる警告です。メソッドの名前を代わりのような名前に変更するとsaveData:、警告が消えるに違いありません。

于 2010-05-14T22:05:06.843 に答える
9

また、Cocoaのメモリ管理ガイドラインに関係なく、コピーがメソッドの最適な名前であるため、本当に「コピー」などでメソッドに名前を付けたい場合は、メソッドの宣言に注釈を付けることができます。そうするとNS_RETURNS_NOT_RETAINED、Clangは指定しません。あなたに警告。それで:

// Copies data from data to string; does not follow the copy rule
- (NSString*)copyData:(NSData*)data NS_RETURNS_NOT_RETAINED;
于 2010-08-06T17:55:06.627 に答える
4

メソッドには名前が含まれているため、メモリ管理ガイドcopyによると、アナライザは返されたオブジェクトに+1の保持カウントがあることを期待しています。

于 2010-05-14T22:06:34.217 に答える
4

いいえ、それは正しくありません。メソッドに"alloc"、 "copy"、 "new"、またはオブジェクトが呼び出し元によって所有されることを意味する他のキーワードの1つが含まれていない限り、メソッドは自動解放されたオブジェクトまたはその他の方法で管理されたオブジェクトを返すため、stringByAppendingPathComponentは自動解放された文字列を返します。

その上、メソッド「copyData」には「copy」という単語が含まれています。これは、結果が呼び出し元によって所有(および解放)される必要があることを意味します。ただし、返された結果は自動リリースされているため、エラーメッセージが表示されます。エラーを修正したい場合は、自動解放しないでください。あれは:

 return [path retain]

もちろん、それはあなたの関数の呼び出し元がそれを解放する必要があることを意味します。または、メモリ管理ガイドラインに準拠するように関数の名前を変更することもできます。

「copyData」という名前、IMHOは、とにかく直感的ではありません。関数の名前を「pathToSavedDataWithData」などに変更することをお勧めします。それが実際に何をしているのかを言う何か。

于 2010-05-14T22:14:30.830 に答える
0

これを突き刺して、ルーチンの名前が「copy ...」で始まっているかどうかに関係なく、まったく同じエラーメッセージが表示されると思います。私はちょうど同様のシナリオに行き着きました、そして、「コピー」は私が呼んでいたルーチンの名前の一部ではありませんでした。自動解放されたオブジェクトを返していたという理由だけで、Clangはエラーメッセージを表示していました。これは危険な状況です。を行う

  return [path retain]  

マイケルが推奨する最後のトリックが問題を処理しました。

于 2011-02-19T19:12:04.893 に答える