开发者

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

开发者 https://www.devze.com 2023-03-22 03:12 出处:网络
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 wonder

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

精彩评论

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