开发者

How to make clear to Clang static analyzer when something's not leaking?

When using Clang static analyzer to analyze my Objective-C code for iOS, I get lots of "potential leaks". Many of the leaks make me wonder why it's erroneous at all. One example that left me wondering in particular was the following:

I have a class-variable of type NSDictionary, used for storing some settings. Now when I have a method to change something inside the dictionary:

- (void) loadPassengerCompartiments {
    NSMutableArray *paxCompartiments = [self.outputTable objectAtIndex:2];
    NSArray *paxCompSrc = [self.values objectForKe开发者_Go百科y:@"PassengerCompartiments"];

    for(MassPerson *passenger in paxCompSrc) {
=>      [paxCompartiments addObject:[[PaxCompartimentOutputField alloc] initWithPerson:passenger]];
    }
}

Clang errs at the in-line allocation and direct association of PaxCompartimentOutputField. When running this code in instruments it doesn't leak.

Two ways I could come up with to solve this are:

  1. use autorelease
  2. replace the in-line allocation with the following code:

(code)

PaxCompartimentOutputField *field = [[PaxCompartimentOutputField alloc] initWithPerson:passenger];
[paxCompartiments addObject:field];
[field release];

The first option is obsolete imho (and especially on iOS its use is discouraged) The second option is pretty bulky - especially when creating an array with more objects (say 10 objects loading default settings).

I don't want to ignore Clang's warnings, as it is an excellent tool for finding bugs & leaks. What is the 'right' way to do this in Objective-C for those cases?


That is a leak.

Since you alloc-init PaxCompartimentOutputField, you own it and you must relinquish ownership of it.

You have 3 options (you already mentioned 2 of them):

1) Use a convenience constructor, when one is available, or in a custom class, declare one. Convenience constructors return objects you do not own, typically by sending an autorelease message to the object they return. It would look like this:

[paxCompartiments addObject:[PaxCompartimentOutputField paxCompartimentOutputWithPerson:passenger]];

2) Use autorelease.

[paxCompartiments addObject:[[[PaxCompartimentOutputField alloc] initWithPerson:passenger]] autorelease];

3) Use a temporary variable.

PaxCompartimentOutputField *tempField = [[PaxCompartimentOutputField alloc] initWithPerson:passenger];
[paxCompartiments addObject:tempField];
[tempField release];


There is a list of source annotations that you can use with Clang.

These might help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜