2011-06-25 8 views
4

私は私のiOSアプリにファイルパスを取得するには、次のコードを持っている:なぜ静的なNSStringは漏れますか?

static const NSString * fullPathFromRelativePath(NSString *relPath) 
{ 
    // do not convert a path starting with '/' 
    if(([relPath length] > 0) && ([relPath characterAtIndex:0] == '/')) 
     return relPath; 

    NSMutableArray *imagePathComponents = [NSMutableArray arrayWithArray:[relPath pathComponents]]; 

    NSString *file = [imagePathComponents lastObject];  
    [imagePathComponents removeLastObject]; 

    NSString *imageDirectory = [NSString pathWithComponents:imagePathComponents]; 

    NSString *fullpath = [[NSBundle mainBundle] pathForResource:file 
                 ofType:NULL 
                inDirectory:imageDirectory]; 
    if (!fullpath) 
     fullpath = relPath; 

    return fullpath;  
} 

static const char * fullCPathFromRelativePath(const char *cPath) 
{ 
    NSString *relPath = [NSString stringWithCString:cPath encoding:NSUTF8StringEncoding]; 
    const NSString *path = fullPathFromRelativePath(relPath); 
    const char *c_path = [path UTF8String]; 
    return c_path; 
} 

static const char * relativeCPathForFile(const char *fileName) 
{   
    NSString *relPath = [NSString stringWithCString:fileName encoding:NSUTF8StringEncoding];   
    const NSString *path = fullPathFromRelativePath(relPath); 
    const char *c_path = [[path stringByDeletingLastPathComponent] UTF8String];  
    return c_path; 
} 

私がデバッグコンソールでは、このようなかなりの数のメッセージを取得しています:

objc[4501]: Object 0x6e17060 of class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug 
objc[4501]: Object 0x6e12470 of class NSPathStore2 autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug 
objc[4501]: Object 0x6e12580 of class __NSCFData autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug 

に問題は何コード? (私はiOS 5を "自動"保持/解放などで使用しています)

乾杯。

答えて

11

このメッセージは、スタックにリリースプールがないスレッドでオブジェクトを自動解放すると表示されます。デフォルトでは、メインスレッドには常に自動解放プールがあります。これは、アプリケーションのmain()関数によって通常呼び出されるUIApplicationMain()関数内で作成され、管理されます。しかし、あなたが作成した追加のスレッド(performSelectorInBackground:またはNSThread)は、そこに特別に置かない限り、自動解放プールを配置しません。そのため、バックグラウンドスレッド上の自動解放オブジェクトには後で解放するプールがなく、

バックグラウンドスレッドに何か不便な点がある場合は、まず自動解放プールを作成する必要があります。 ARCの下では、新しい@autoreleasepool構造を使用してください。

+0

ねえ、この答えは正しいです。私はココアのAPIを介してより多くのスレッドを作成していなかったが、いくつかの新しいスレッドは、この問題の原因は、低レベルのC関数で作成されていた。私は@autoreleasepoolの周りに最初のメソッドをラップし、問題は修正されました。 まだARCの周りに私の頭を包んで:) – Goles

0

私はそれが本当のリークだとは思わない。 Appleはこれを数回述べていますが、シミュレータ上ではシミュレータライブラリがNSAutoReleasePoolをどのように扱うのかはよく知られていますが、Macよりもかなり多くのメモリが搭載されているため、 WWDCでは、NSZombieがautoreleaseを正しく扱っていない場所がいくつかあると言いましたが、どのセッションがあったのか覚えていません。インスツルメンツのオブジェクトのリークに気付かない限り、心配する必要はありませんそれ。計測器を使用して漏れを検出した場合は、bugreportを提出してください。

メソッドの周囲に自動解放プールを作成しないでください。漏れているように見えるからです。とにかく動作しないARCで、あなたのアプリケーションのmain()関数を変更しない限り、のすべてをとする自動解放プールがあります。そのメソッドが呼び出された後に重大なメモリ圧迫を示すデータをプロファイリングせずに余分な自動解放プールを作成すると、アプリケーションが実際に悪化します。

+0

バックグラウンドスレッドでコードを取得していれば、すべてをラッピングする自動解放プールはありません。 UIKitが自動的に作成する自動解放プールは、メインスレッドのみに適用されます。 –

+0

それは本当であり、Appleがブロック&GCDを使用するためにdevsにプッシュする主要な理由の1つになっている可能性があります。しかし、OPはバックグラウンドスレッドでの作業は言及していません... – RyanR

+1

いいえ、OPはバックグラウンドスレッドは言及していませんでしたが、UIApplicationMain()を呼び出さないようにmain()を変更していない限り、ほとんど例外なくバックグラウンドスレッドで発生します。 –

0

これは、main.mファイルでNSAutoreleasePool呼び出しを削除した場合、またはこのコードが別のスレッドで実行されている場合に発生します。 ARCでNSAutoreleasePoolを使用することはできませんので、@autoreleasepoolブロックにスレッドコードを入れてください。

+0

NSAutoreleasePool [ARCプロジェクトで使用することはできません](http://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html)。それはコンパイルされません。 – RyanR

+0

NSAutoreleasePoolオブジェクトは使用できません。 ARCは代わりに@autoreleasepoolブロックを提供します。これらは、NSAutoreleasePoolよりも効率的であるという利点があります。 – edo42

+0

あなたが私に与えたページからコピーされました – edo42

1

非ARCアプリケーションで同じコードを実行しようとしましたか?これを行うことで、ARCの問題かフレームワークの本当のバグかどうかを確認できます。 ARCはまだ未成熟ですが、Appleは何度もこれが行われておらず、間違いなくバグがあると述べています。

作成される見かけ上の自動解放オブジェクトの数が気になる場合は、該当するコードの周囲に@autoreleasepool {...}構成を使用してください。とにかくARCコードでは作成できないNSAutoreleasePoolよりも相当に多いのはmore efficientです。

+0

ありがとう!、まだARCに慣れています:)。 @autoreleasepoolの最初のメソッドでコードを折り返して、問題を修正しました。 (それは@autoreleasepoolで、@autoreleaseではない) – Goles

関連する問題