Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can this Xcode Clang static analyzer warning be suppressed?

"Potential leak of an object allocated on line n and stored into 'variable'."

Normally this is a very helpful analyzer warning, but there are a few situations where I get annoying false positives that I would like to suppress to keep my analyzer results clean. In the analyzer's defense, what it's noticing would definitely be a memory leak were it not for a release in another path of execution (to which it is blind).

I'll elaborate on my situation. It happens in various flavors, but the general pattern is as follows:

  1. An object is allocated and its delegate is set.
  2. Something is done with the object. (A task started, a view displayed, etc).
  3. Execution of current method ends. (Enter Clang warning).
  4. Object decides its task is complete, sends delegate a message.
  5. Delegate releases object.

This is not at all an esoteric design pattern, so I'm hoping suppression is possible. I know it can be avoided by storing the offending object in an ivar that is later released, but I greatly prefer to not add ivar pollution.

like image 832
Matt Wilding Avatar asked Feb 10 '11 01:02

Matt Wilding


People also ask

What is Clang static analyzer?

The Clang Static Analyzer is a source code analysis tool that finds bugs in C, C++, and Objective-C programs. It implements path-sensitive, inter-procedural analysis based on symbolic execution technique.

How do I run static analyzer in Xcode?

It's very easy to run. Just go to Product and choose Analyze, or use the keyboard shortcut Command-Shift-B. You can see the analyzer running in the status bar of Xcode.


2 Answers

Clang has a few new Source Annotations. In specific, you may be interested in the ns_consumed attribute.

like image 76
Lily Ballard Avatar answered Oct 01 '22 04:10

Lily Ballard


I think you should heed the static analyser message in this case. Your pattern has potential problems.

Specifically, when you return from the method invoked to do step 5, you are in a method of an object that may already have been deallocated. I interpret your pattern something like this:

// steps 1, 2, 3
-(void) methodThatCreatesObject
{
    id theObj = [[TheObj alloc] init];
    [theObj setDelegate: delegateObj];
    // other stuff
}

Note the above breaches the memory management rules

// step 4 - a method of theObj
-(void) someMethod
{
    [delegate notifyTaskCompleteFromObj: self];
    // self points to an invalid object here.  Doing anything with self results in EXC_BAD_ACCESS
}

The above breaches an assumption stated in the memory management rules:

A received object is normally guaranteed to remain valid within the method it was received in

if we say self is a received object, which it is technically, since it is passed as a parameter on the stack.

// step 5 the delegate method defined in the delegate object

-(void) notifyTaskCompleteFromObj: (TheObj*) anObj
{
    // do stuff
    [anObj release];
}

The above also breaches the memory management rules.

The normal pattern is to have a controller that owns both the delegate and the object that has the delegate (often the controller is itself the delegate). I think you should move to that pattern.

like image 36
JeremyP Avatar answered Oct 01 '22 05:10

JeremyP