11

基础是我有一个自定义的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>.

当我 break onauto_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 类型被不当释放有关?

4

6 回答 6

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;
}
于 2011-01-12T18:21:49.277 回答
3

这是 _NSCFURLProtocolBridge 实现中的一个错误。

请使用http://bugreport.apple.com/并提交错误。如果您包含此页面的 URL,将不胜感激(如果您使用 Radar # 更新此页面,也将不胜感激)。理想情况下,如果您可以附加屏幕保护程序的二进制文件,那将非常有帮助;不需要来源。

幸运的是,它不会导致崩溃。不幸的是,它可能会导致泄漏。

于 2009-08-05T03:44:32.833 回答
1

此错误通常表示对象被保留-retain,但被释放CFRelease()。如果您认为这不可能是您的对象(这不是一个可怕的信念),那么您应该打开另一个雷达。但是您应该首先环顾四周,看看是否有您正在使用的 CF 对象-retain,也许您应该使用CFRetain().

剩下的就是在黑暗中拍摄......

您可以通过提升堆栈并查看传递给这些 C++ 方法(或特别是auto_zone_release)的参数来获得一些见解。在 gdb 中尝试此操作以尝试查看第一个参数中的内容:

p *($esp)

看看你是否能得到关于被传递对象的任何见解。如果幸运的话,也许这会起作用:

po (id)(*($esp))
于 2009-07-28T00:17:36.720 回答
1

我通过CFRetain-ing 客户端解决了这个问题,并CFRelease在下次调用时再次 -ing 它startLoading

-(void)startLoading 
{
        if ( client ) CFRelease(client);
        client = [self client];
        CFRetain(client);

当然,在 finalize

-(void)finalize
{
    if ( client ) CFRelease(client);
    [super finalize];
}

clientNSURLProtocol子类的实例变量。

于 2011-01-13T12:09:40.653 回答
1

这是我不久前提交的错误报告:

http://openradar.appspot.com/8087384

可能也值得归档,它已经被复制了,但是修复它会很好。

正如 Alex 所说,一位 Apple 开发人员查看了我面前的源代码,并通过我们的示例轻松找到了问题所在。

于 2011-01-17T05:35:47.167 回答
0

有时在打开对话框过滤器中使用 NSURL 也会出现同样的错误。对我来说,在我不再需要它之后将其显式设置为 nil 就足够了。

于 2011-11-18T12:59:46.920 回答