4

これが私が得るエラーメッセージです:

ContactsWithPN - start loop
Program received signal:  “0”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")

この問題を引き起こすコードは次のとおりです。

+(NSArray *) contactsWithPhoneNumbers{
    NSArray *contacts = [ABContactsHelper contacts];
    NSMutableArray *rv = [[NSMutableArray alloc] init];
    NSLog(@"ContactsWithPN - start loop");
    for (int i = 0; i< [contacts count] ; i++) {
        ABContact * c = (ABContact*)[contacts objectAtIndex:i];
        ABContact * fullContact = [ABContact  contactWithRecordID:[c recordID]];

        if ([[fullContact phoneArray] count] > 0) {
            [rv addObject:fullContact];
        }
    }
    NSLog(@"ContactsWithPN - end loop");
    NSArray *ret = [[NSArray alloc] initWithArray:rv];
    return ret;
}

上記のクラス メソッドを呼び出すビュー コントローラーで、次のコードを追加して、メモリ警告が送信されているかどうかを確認しました。ではない!

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    NSLog(@"InviteFriends - memory warning received");
}

所見: + エラーがさまざまな時点で発生することがわかりました - インデックス 253 で発生することもあれば、246 で発生することもあります。

4

4 に答える 4

6

メモリ警告を受け取っていないという事実は、それが送信されなかったことを意味するわけではありません。メモリ警告はメイン実行ループに配信されます。関数の実行中は配信されません。

代わりに、電話コンソール(Xcode-> Organizer-> Your phone-> Console、またはiPCUの同等のもの)を確認することを検討してください。「メモリレベルが重要です」などと表示され、アプリの強制終了について言及されている場合は、メモリが不足しています。さらに、メモリが不足すると、クラッシュレポーターは、強制終了されたプロセスの横に「jettisoned」を含む「メモリ不足」のクラッシュログを書き込みます。これらはオーガナイザーに表示されます。(iOS 4の「マルチタスク」以降、バックグラウンドタスクにも投棄が発生します。)

自動解放されたオブジェクトの山が大きいことが原因である場合は、明示的な自動解放プールを使用してある程度軽減できます。

for (int i = 0; i< [contacts count] ; i++) {
    NSAutoreleasePool * pool = [NSAutoreleasePool new];

    ...

    [pool drain]; pool = nil;
}

あなたのコードもリークretrvます。

于 2010-10-02T14:16:04.260 に答える
1

このエラーは、アプリのメモリが不足している場合に発生します。Apples Memory Management Guideを読む必要があります。

于 2010-10-02T02:17:57.443 に答える
0

まず、コードにメモリリークがあることです...このように修正してください

+(NSArray *) contactsWithPhoneNumbers{
    NSArray *contacts = [ABContactsHelper contacts];
    NSMutableArray *rv = [[NSMutableArray alloc] init];

    NSLog(@"ContactsWithPN - start loop");
    for (int i = 0; i< [contacts count] ; i++) {
        ABContact * c = (ABContact*)[contacts objectAtIndex:i];
        ABContact * fullContact = [ABContact  contactWithRecordID:[c recordID]];

        if ([[fullContact phoneArray] count] > 0) {
            [rv addObject:fullContact];
        }
    }

    NSLog(@"ContactsWithPN - end loop");
    NSArray *ret = [[NSArray alloc] initWithArray:rv];
    //You need to release rv since you dont need it any more as you have copied the contents to a new array ( this itself is a waste ) so you must release the old array
    [rv release];

    //Now when you return the array you must still not hold object ownership since the function dies after returning so you give it a delayed release which kicks in when the autorelease is flushed.
    return [ret autorelease];
}

通常、autorelease は OS によって決定された特定の時間にフラッシュされますが、独自のプールを作成して、リソースを無駄にしないようにすることができます。したがって、理想的には、このように電話をかけます

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *contactArray = [[self contactsWithPhoneNumbers] retain];
[pool drain];
//This will release the object ownership held by the function

最後に、これをすべて実行すると、メモリリークは発生しませんが、それでもこのエラーが発生します。メモリ警告が@tcのようにあなたに届かなかったため、答え。言った。したがって、簡単な答えは、メインの実行ループが詰まっているということです。できることは、この操作を別のスレッドで実行して、メインループが詰まっていないことを確認することです... iOS 4 以降を使用している場合は、次の方法で簡単に実行できます

dispatch_queue_t otherQueue = dispatch_queue_create("com.company.otherqueue", NULL);
dispatch_async(otherQueue, ^{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *contactArray = [[self contactsWithPhoneNumbers] retain];
    [pool drain];
}
dispatch_release(otherQueue);

これは必ずしも新しいスレッドを作成することを意味するわけではありませんが、メイン キューがブロックされないように OS がキューを管理し、メモリ警告が表示されます。それ以降は、メモリを解放し、オーバーしないようにする必要があります。

于 2011-12-23T06:15:10.433 に答える
0

ABContact もメモリ リークを発見しました。以下の ABContactHelper コードの一部を参照してください。

+ (NSArray *) contacts
{
 ABAddressBookRef addressBook = ABAddressBookCreate();
 NSArray *thePeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
 NSMutableArray *array = [NSMutableArray arrayWithCapacity:thePeople.count];
 for (id person in thePeople)
 {
  [array addObject:[ABContact contactWithRecord:(ABRecordRef)person]];
 }
 [thePeople release];
        //I think need CFRelease(addressBook); here
 return array;
}
于 2010-11-24T02:23:13.287 に答える