基础知识是我有自定义NSURLProtocol
。在startLoading
中,[self client]
的类型为:
<_NSCFURLProtocolBridge> {NSURLProtocol, CFURLProtocol}
问题是在垃圾收集环境中运行。因为我正在写一个屏幕保护程序,所以我不得不把它垃圾收集起来。但是,_NSCFURLProtocolBridge协议似乎总是抛出:
malloc: reference count underflow for (memory_id_here), break on auto_refcount_underflow_error to debug
调试控制台的示例转储是:
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.
您可以看到<_NSCFURLProtocolBridge 0x20025ab00>
发生了下溢。
当我在auto_refcount_underflow_error
上突破时,似乎堆叠追溯到URLProtocolDidFinishLoading:
:
id client = [self client];
...
[client URLProtocolDidFinishLoading:self];
这个问题似乎已经存在了一段时间,但在网上似乎根本没有答案:
http://lists.apple.com/archives/cocoa-dev/2008/May/msg01272.html http://www.cocoabuilder.com/archive/message/cocoa/2007/12/17/195056
该错误仅在垃圾收集环境中显示这些列出的错误。有关如何在不引起内存问题的情况下解决此问题的任何想法?我假设这可能与NSURLProtocol下面的CF类型发布不正确有关?
答案 0 :(得分:4)
上次WWDC我们通过webkit工程师确认了这个错误,他可以在代码中看到错误,所以希望他们能解决它。解决方法是在initWithRequest方法中CFRetain客户端。
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client
{
// work around for NSURLProtocol bug
// note that this leaks!
CFRetain(client);
if (self = [super initWithRequest:request cachedResponse:cachedResponse client:client])
{
}
return self;
}
答案 1 :(得分:3)
这是_NSCFURLProtocolBridge实现中的一个错误。
请使用http://bugreport.apple.com/并提交错误消息。如果您包含此页面的URL,那将不胜感激(如果您使用Radar#更新此页面,也将受到赞赏)。理想情况下,如果您可以附加屏幕保护程序的二进制文件,那将非常有用;无需任何来源。
幸运的是,它不应该导致崩溃。不幸的是,它可能会导致泄漏。
答案 2 :(得分:1)
此错误通常表示某个对象与-retain
一起保留,但随CFRelease()
一起发布。如果你认为这不是你的目标(这不是一个可怕的信念),那么你应该打开另一个雷达。但是你应该首先环顾四周,看看你使用-retain
时是否有使用CFRetain()
的CF对象。
剩下的就是在黑暗中拍摄......
您可以通过加强堆栈并查看传递给这些C ++方法的参数(或特别是auto_zone_release
)来获得一些见解。在gdb中尝试这个以尝试查看第一个参数中的内容:
p *($esp)
看看你是否能够对传递的对象有所了解。如果你幸运的话,也许这会奏效:
po (id)(*($esp))
答案 3 :(得分:1)
我通过CFRetain
- 客户端解决了这个问题,CFRelease
在下次调用startLoading
-(void)startLoading
{
if ( client ) CFRelease(client);
client = [self client];
CFRetain(client);
当然,最终确定
-(void)finalize
{
if ( client ) CFRelease(client);
[super finalize];
}
client
是NSURLProtocol
子类的实例变量。
答案 4 :(得分:1)
以下是我提交过的错误报告:
http://openradar.appspot.com/8087384
也可能值得归档,它已经被重复了,但修好它会很好。
正如Alex所说,Apple开发人员在我面前查看了源代码,并使用我们的示例轻松找到了问题。
答案 5 :(得分:0)
有时在打开的对话框过滤器中使用NSURL会出现相同的错误。 对我来说,只要我不再需要它就足够明确地将其设置为nil。