views:

638

answers:

2

The basics are I have a custom NSURLProtocol. In startLoading, [self client] is of type:

<_NSCFURLProtocolBridge> {NSURLProtocol, CFURLProtocol}

The problem is running this in a garbage-collected environment. Because I'm writing a screensaver, I'm forced to make it garbage-collected. However, the _NSCFURLProtocolBridge protocol seems to always throw:

malloc: reference count underflow for (memory_id_here), break on auto_refcount_underflow_error to debug

An example dump to the debug console is:

ScreenSaverEngine[1678:6807] client is <_NSCFURLProtocolBridge 0x20025ab00> {NSURLProtocol 0x200258ec0, CFURLProtocol 0x20029c400} ScreenSaverEngine(1678,0x102eda000) malloc: reference count underflow for 0x20025ab00, break on auto_refcount_underflow_error to debug.

You can see that the underflow occurs for <_NSCFURLProtocolBridge 0x20025ab00>.

When I break on auto_refcount_underflow_error, it seems to stack-trace back up to URLProtocolDidFinishLoading: in:

id client = [self client];
...
[client URLProtocolDidFinishLoading:self];

This problem seems to have existed for a while, but there seems to be no answer at all online:

http://lists.apple.com/archives/cocoa-dev/2008/May/msg01272.html http://www.cocoabuilder.com/archive/message/cocoa/2007/12/17/195056

The bug only shows itself in garbage-collected environments for these listed bugs as well. Any thoughts on how I can work around this without causing memory issues? I'm assuming this probably has something to do with the CF type underneath NSURLProtocol being released improperly?

+1  A: 

This error generally indicates that an object was retained with -retain, but released with CFRelease(). If you believe that this could not be your object (and that's not a terrible belief), then you should open another Radar. But you should first look around and see if there's a CF object you're using -retain on when perhaps you should use CFRetain().

The rest of this is shooting in the dark....

You may gain some insight by stepping up the stack and looking at the parameters that are being passed to these C++ methods (or particularly auto_zone_release). Try this in gdb to try to see what's in the first parameter:

p *($esp)

And see if you can get any insight about the object being passed. Perhaps this will work if you're lucky:

po (id)(*($esp))
Rob Napier
Rob - in a GC environment, aren't -retain calls NOOPs? I do think this is a bug and I will open a Radar bug about it. Thanks!
Dave Martorana
-retain is a NOOP in GC, but CFRetain() is not. So if you call -retain and then CFRelease(), you'll get unbalanced.
Rob Napier
+3  A: 

It is a bug in the implementation of _NSCFURLProtocolBridge.

Please use http://bugreport.apple.com/ and file a bug. If you include the URL to this page, that would be appreciated (and if you update this page with the Radar #, that would be appreciated, too). Ideally, if you can attach a binary of your screensaver, that would be very helpful; no source needed.

Fortunately, it should not cause a crash. Unfortunately, it probably causes a leak.

bbum