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>

私が中断する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 タイプが不適切にリリースされたことと関係があると思いますか?

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

しばらく前に提出したバグレポートは次のとおりです。

http://openradar.appspot.com/8087384

おそらく同様に提出する価値があります。すでに複製されていますが、修正されるとよいでしょう。

アレックスが言ったように、Apple の開発者が私の目の前のソース コードを見て、私たちが持っていた例で問題を簡単に突き止めました。

于 2011-01-17T05:35:47.167 に答える
1

CFRetainクライアントをCFRelease-ing し、次の呼び出しで再度 -ing することで、この問題を回避しました。startLoading

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

そしてもちろん、ファイナライズで

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

clientNSURLProtocolサブクラスのインスタンス変数です。

于 2011-01-13T12:09:40.653 に答える
1

通常、このエラーは、オブジェクトが で保持され-retain、 でリリースされたことを示しますCFRelease()。これが目的ではないと思われる場合 (それはひどい信念ではありません)、別のレーダーを開く必要があります。しかし、最初に周りを見回して-retain、おそらくCFRetain().

残りは暗闇での撮影です....

スタックをステップアップし、これらの C++ メソッド (または特に ) に渡されるパラメーターを調べることで、洞察を得ることができますauto_zone_release。これを gdb で試して、最初のパラメーターの内容を確認してください。

p *($esp)

そして、渡されたオブジェクトについて洞察を得ることができるかどうかを確認してください。運が良ければ、おそらくこれでうまくいくでしょう:

po (id)(*($esp))
于 2009-07-28T00:17:36.720 に答える
0

開いているダイアログ フィルターで NSURL を使用すると、同じエラーが発生することがあります。私にとっては、不要になった後に明示的に nil に設定するだけで十分でした。

于 2011-11-18T12:59:46.920 に答える