开发者

Ignore 'Object sent -autorelease too many times" warning

When running Analyzer, I receive the "Object sent -autorelease too many times" warning. I know I'm doing something tricky (and am open to alternatives to accomplishing my goal).

Essentially, I wanted to keep a stack of specific types of controllers handy for sending messages from a central location. So, considering:

From 'ActionBroker' shared object:

NSMutableSet *liveActions;
liveActions = [NSMutableSet alloc] init];

...

CLViewController *action = [[[actionClass alloc] init] autorelease];
if (!action) {
    return nil;
}    
[self.liveActions addObject: action];
// When adding an object, the retain count is increased. We want the action
// to dealloc, so that it might remove itself from the list...
[action release];
return action;    

And the complementary dealloc code:

[[CLActionBroker 开发者_运维百科sharedActionBroker] removeAction: self];        
[super dealloc];

... and in removeAction:

[action retain];
[self.liveActions removeObject:action];

The above code works, I just get the nagging error. And the nagging sensation that I could probably solve the problem a different way.

One of the use cases for this code is to pass an 'handleOpenURL' request through a chain of open controllers and returning the first 'YES' response.


As I understand it, your intent is to have a set of controllers ("actions") in the set, which you could easily access from anywhere in your app. If one of these controllers is deallocated, it would automatically remove itself from the set.

There's a problem with this setup, though. As you've described it above, the controller is supposed to be removed from the liveActions set upon deallocation. But since an NSSet retains its members, your controller will never be deallocated so long as it is still in the liveActions set. -dealloc is only run when all retains have been balanced by a release.

This, then leads to your over-release, which leads to the warning. Since you've sent an extra release, -dealloc could be run while the controller is still in the liveActions set. But when you remove it from that set, it's going to send a release message to your object, which would take its retain count negative. That may or may not be safe, but in either case it's an ugly workaround.

What you really want, it seems, is a set that does not retain its members. This is normally a dangerous configuration, since it can lead to dangling pointers in the set. But if you're willing to manage the lifetime of the object and clear out those dangling pointers at the appropriate times, it turns out that it's quite doable. You just need to use a CFMutableSet instead of an NSMutableSet. And since the two are toll-free bridged, it doesn't even add that much complexity.

Setting up the CFMutableSet looks like this:

// The NULL for the third parameter tells the set to not do anything when
// an object is added to or removed from the set.
CFMutableSetRef cfLiveActions = CFSetCreateMutable(NULL, 0, NULL);

// Toll-free bridging makes this possible
NSMutableSet *liveActions = (NSMutableSet *)cfLiveActions;

After that, you can use it exactly as you would use any other NSMutableSet; this one will just be special in that it won't retain its members.


The problem:

CLViewController *action = [[[actionClass alloc] init] autorelease]; // +0 ownership
// ...
[self.liveActions addObject: action]; // liveActions takes ownership
// ...
[action release]; // -1 ownership

When you've alloced the object, you are responsible for it. But then when you autorelease it, you've fulfilled your obligation (and because you autoreleased instead of releasing, you can still use the object until the next turn of the runloop). You shouldn't release it again later.

Also:

[action retain];
[self.liveActions removeObject:action];

The retain is unnecessary.

(And here's another plug for beginning to switch to ARC, under which you won't have to worry about this!)

[Edit: misunderstood your question. Revised answer forthcoming.] [Edit 2: never mind... even though I misread your intent, I believe my solution is still right.]

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜