init method and “Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected” - false positive?

StackOverflow https://stackoverflow.com/questions/9874608

  •  26-05-2021
  •  | 
  •  

Frage

First of all: I understand, why this warning is existing, I just can't explain myself, why it is triggered under these circumstances. The official Cocoa memory management policy is as following: "You own any object you create You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).

You can take ownership of an object using retain"

I know have code like this:

- (id) foo
{
    // do something
    return self;
}

- (id) init
{
    self = [super init];
    return [self foo]; // clang static analyzer is complaining about returning an object with a +0 retain count here, although a +1 would be expected
}

Afaik this is a false positive from clang, isn't it? I mean, the only methods, which increase the retain-count, are "retain" and all methods, whose names begin with "alloc", "new", "copy", or "mutableCopy", so "init" is not increasing the retain-count, but relays on the caller, to pass in the return-value of the class' "alloc"-method, so actually "init" is expected to return a +0 retain count, not a +1 one, isn't it? It just returns the object with the same retain count, with which it has been passed in. Now calling "foo" on that object also does not change the retain count, so this code should be perfectly legal and in fact it works just fine and the retain count is correct all over the whole life time of the program, only the static analyzer is complaining.

War es hilfreich?

Lösung

The method name foo by convention means that it returns an object that the caller does not own.

alloc-init*** combinations return an object that the caller owns.

Looks like the analyzer can't or doesn't bother to look inside foo to see what it's actually doing, and does not know that the returned value is the same object as the already owned self.

It is not a false positive. If a subclass, or a dynamically loaded category override foo to return something else:

- (id) foo; {
    return [NSNumber numberWithInt:666];
}

then you will have a leak of self and an over-release of NSNumber object.

Andere Tipps

Yes, this is a false-positive, but this is a bad practice to use when designing a class. Instead, you should call foo, then return self, like so:

-(id) init
{
    if ((self = [super init]))
    {
        [self foo];
    }

    return self;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top