0

昨日まで、プロパティのメモリ管理がどのように機能するかを理解していると思っていましたが、XCode で「分析」タスクを実行したところ、「このオブジェクトはここでは所有されていません」というメッセージがたくさん表示されました。これは私の問題を説明する簡単な例です:

MyObservingObject.h:

@interface MyObservingObject : NSObject
@property(nonatomic, retain) NSMutableDictionary *observedDictionary;
-(id)initWithDictCapacity:(int)capacity;
@end

MyObservingObject.m:

@synthesize observedDictionary;

-(id)initWithDictCapacity:(int)capacity {
    self = [super init];
    if (self) {
        self.observedDictionary = [[[NSMutableDictionary alloc] initWithCapacity:capacity] autorelease];
    }
    return self;
}

- (void)dealloc {
    // The following line makes the Analize action say :
    // "Incorrect decrement of the reference count of an object that is not owned at this point by the caller"
    [self.observedDictionary release], self.observedDictionary=nil;

    [super dealloc];
}

私が理解できないのは、なぜこのプロパティを呼び出さず release にそのままにしておく必要があるのですか? My@propertyretain(copy同じことをします) に設定されているので、 を実行するself.myRetainProperty = Xと、X の保持カウントが増加します (自己所有) ですね。

4

4 に答える 4

2

セッターに解放を行わせる必要があるため、 in への呼び出しを削除しreleaseますdealloc

- (void)dealloc {
    self.observedDictionary=nil;

    [super dealloc];
}

これは、セッターが次のようなものに合成されるためです。

- (void)setObject:(id)object
{
    [object retain];
    [_object release];
    _object = object;
}

を渡すと、希望どおりに機能しますnil

于 2013-02-08T14:14:08.063 に答える
1

増加しましたが、 に設定するとnil、setter メソッドは最初にバッキング インスタンス変数を解放し、それから新しい値を保持して割り当てます。したがって、プロパティnilに設定するだけで十分ですが、ivarをに設定するとnilメモリ リークが発生します。

理解を深めるために、自動生成された保持セッターの典型的な実装は、次のようなものと同等です

- (void)setFoo:(id)foo
{
    if (_foo != foo) {
        [_foo release];
        _foo = [foo retain];
    }
}

また、結果として、このようなプロパティをリリースしないでください。これを行うと、バッキング ivar の割り当てが解除され、(後でreleaseプロパティを設定するときにアクセサーによって) メッセージングnilがクラッシュする可能性があります。

于 2013-02-08T14:14:47.577 に答える
1

あなたがする必要はありません

[self.observedDictionary release]

self.observedDictionary=nil;

これはプロパティであり、リリースを以前の値に自動的に送信するため、これで十分です。

self.observedDictionary=nil;
于 2013-02-08T14:13:29.180 に答える
0

コンパイラの警告の理由は、オブジェクトを取得する方法が原因です。

電話することで

[self.observedDictionary release];

実際には、次のように定義されたアクセサ メソッドを使用しています。

- (NSDictionary *)observedDictionary;

これはオブジェクトを返しますが、コンパイラの命名によりobservedDictionary、所有権の譲渡がないことを前提としています。たとえば、呼び出し先はさらに保持しない限り、このオブジェクトを解放する必要はありません。このため、実際には所有していないオブジェクトを解放することでオーバーリリースを行うとコンパイラが判断します。

copyより具体的には、所有権を譲渡するメソッド名の規則は、 、mutableCopyallocまたはで始まりnewます。

いくつかの例

ここでは、所有権の譲渡を意味しない名前を使用しているため、警告が表示されます

- (id)object;
{
  return [[NSObject alloc] init];
}
//=> Object leaked: allocated object is returned from a method whose name ('object') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'.  This violates the naming convention rules given in the Memory Management Guide for Cocoa

修正 1: (所有権を譲渡しないでください)

- (id)object;
{
  return [[[NSObject alloc] init] autorelease];
}

修正 2: (名前をより適切にする)

- (id)newObject;
{
  return [[NSObject alloc] init];
}

この知識があれば、命名規則を理解できます。返されたオブジェクトを所有していないため、以下が間違っていることがわかります。

[self.object release]; //=> Produced warnings

そして最後の例を示すために - その名前で所有権の譲渡を意味するオブジェクトを解放する

[self.newObject release]; //=> No Warning
于 2013-02-08T14:29:08.607 に答える