3

.plist ファイルを使用して、iCloud を使用してデバイス間でデータを同期する Mac および iOS 用のアプリがあります。ときどき、特定のデバイスでクラッシュが繰り返されるというメールを誰かから受け取ります。(他のデバイスは問題ありません。) いずれの場合も、データを辞書に変換するために NSPropertyListSerialization を使用して、iCloud からファイルを読み込もうとしているときにアプリがクラッシュしました。いずれの場合も、ユーザーにアプリの iCloud データを削除してもらうことで問題は解決します。同じファイルが再び同期され、すべてが再び正常に機能します。

ここで使用する特定の例は Mac バージョンのものですが、iOS でもほぼ同じクラッシュが発生しました。クラッシュレポートから:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: 0x000000000000000a, 0x0000000101ee2000

VM Regions Near 0x101ee2000:
    VM_ALLOCATE            0000000101ee1000-0000000101ee2000 [    4K] rw-/rwx SM=PRV  
--> mapped file            0000000101ee2000-0000000101ee3000 [    4K] r--/rwx SM=COW  /Users/USER/Library/Mobile Documents/PB4R74AA4J~com~junecloud~Notefile/*/*.notefile
    shared memory          0000000101ee3000-0000000101ee4000 [    4K] rw-/rw- SM=SHM  

その後:

Thread 7 Crashed:
0   libsystem_c.dylib               0x0000000105157013 bcmp + 19
1   com.apple.CoreFoundation        0x0000000101bbf4b0 __CFBinaryPlistGetTopLevelInfo + 80
2   com.apple.CoreFoundation        0x0000000101bbf36d __CFTryParseBinaryPlist + 93
3   com.apple.CoreFoundation        0x0000000101bbede2 _CFPropertyListCreateWithData + 146
4   com.apple.CoreFoundation        0x0000000101bcbdb0 CFPropertyListCreateWithData + 112
5   com.apple.Foundation            0x0000000101568b89 +[NSPropertyListSerialization propertyListWithData:options:format:error:] + 94
6   com.junecloud.Notefile-Helper   0x000000010107ad06 -[JUNNoteDocument readFromData:ofType:error:] + 64
7   com.apple.AppKit                0x000000010268d507 -[NSDocument readFromURL:ofType:error:] + 546
8   com.apple.AppKit                0x000000010228e3c8 -[NSDocument _initWithContentsOfURL:ofType:error:] + 135
9   com.apple.AppKit                0x000000010228e074 -[NSDocument initWithContentsOfURL:ofType:error:] + 262
10  com.junecloud.Notefile-Helper   0x000000010107cad8 -[JUNSyncDocument initWithFileURL:] + 213
11  com.junecloud.Notefile-Helper   0x0000000101079ec7 -[NotefileAppDelegate documentForURL:] + 68
12  com.junecloud.Notefile-Helper   0x00000001010825cb -[JUNSyncManager documentForURL:] + 76
13  com.junecloud.Notefile-Helper   0x000000010107d43c -[JUNSyncInOperation main] + 1340
14  com.apple.Foundation            0x0000000101563cd2 __NSThread__main__ + 1345
15  libsystem_c.dylib               0x00000001051697a2 _pthread_start + 327
16  libsystem_c.dylib               0x00000001051561e1 thread_start + 13

Thread 7 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000062  rbx: 0x000000000000007b  rcx: 0x000000010c2be868  rdx: 0x0000000000000007
  rdi: 0x0000000101d1e151  rsi: 0x0000000101ee2000  rbp: 0x000000010c2be810  rsp: 0x000000010c2be7b8
   r8: 0x000000010c2be870   r9: 0x0000000000000000  r10: 0x00007ff841c28900  r11: 0x00007ff841c186d8
  r12: 0x000000010c2be870  r13: 0x0000000101ee2000  r14: 0x000000010c2beb00  r15: 0x000000010c2be980
  rip: 0x0000000105157013  rfl: 0x0000000000010202  cr2: 0x0000000101ee2000
Logical CPU: 2

クラッシュしている関連するコードは次のとおりです。

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
    BOOL success = NO;
    NSDictionary *dictionary = nil;

    NSError *error = nil;
    id plist = [NSPropertyListSerialization propertyListWithData:data
        options:NSPropertyListImmutable format:NULL error:&error];
    if (plist && [plist isKindOfClass:[NSDictionary class]]) {
        dictionary = plist;
    } else {
        NSLog(@"Error opening document: %@ %@",error,[error userInfo]);
        if (outError != NULL) *outError = error;
    }

    // Then it does some things with the dictionary if it's not nil

    return success;
}

NSPropertyListSerialization が壊れたデータを詰まらせているだけだと思う​​のは正しいですか、それとも自分のコードで問題が発生する可能性が高いですか? 問題が NSPropertyListSerialization にある場合、アプリのクラッシュを防ぎ、問題をより適切に処理するためにできることはありますか?

問題が自分のコードにある可能性が高い場合、原因を追跡するにはどうすればよいですか? 自分で問題を再現できれば、これははるかに簡単になりますが、自分のデバイスでこのクラッシュを見たことはありません。明らかに、ユーザーが自分の iCloud アカウントへのアクセスを許可してくれるとは期待できません。

更新リクエストに応じて、ここに少しJUNSyncDocument. iOS ではこれは UIDocument サブクラスであり、Mac では NSDocument サブクラスです。

- (id)initWithFileURL:(NSURL *)url {
    #if TARGET_OS_IPHONE

    self = [super initWithFileURL:url];
    return self;

    #else

    NSError *error = nil;
    if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
        if ((self = [super initWithContentsOfURL:url ofType:[self documentType] error:&error])) {
            self.fileURL = url;
            self.hasUndoManager = NO;
        } else NSLog(@"Error initializing existing document: %@ %@",url,error); 
    } else {
        if ((self = [super initWithType:[self documentType] error:&error])) {
            self.fileURL = url;
            self.hasUndoManager = NO;
        } else NSLog(@"Error initializing new document: %@",error);
    }
    return self;

    #endif
}

これはごちゃごちゃしているように見えます。ここでばかげたことをしていても驚かないでしょう。ただし、ほとんどの場合は問題なく動作します。それはから呼び出されNotefileAppDelegateます:

- (JUNSyncDocument *)documentForURL:(NSURL *)url {
    JUNNoteDocument *document = [[JUNNoteDocument alloc] initWithFileURL:url];
    return document;
}

これは次のように呼び出されJUNSyncManagerます:

- (JUNSyncDocument *)documentForURL:(NSURL *)url {
    return [self.delegate documentForURL:url];
}

によって呼び出されJUNSyncInOperationます:

JUNSyncDocument *document = [self.delegate documentForURL:self.url];

を使用してそのばかげたデリゲート チェーンを取り除くことができることに気付きましたがNSClassFromString、それが問題に影響するかどうかはわかりません。

4

2 に答える 2

3

ソース を見ると、of __CFTryParseBinaryPlist and __CFBinaryPlistGetTopLevelInfoオープンソースです。

クラッシュしている memcmp (bcmp) は、バイナリ plist ヘッダーのデータの最初の数バイトをチェックする最初の部分にあるようです。バイトだとそこまでいかないので、バッファアンダーフローではありませCFDataGetLengthん。<= 8nil が返される可能CFDataGetBytePtr性はありますが、長さが 8 を超えるとどうなるかわかりません。データ ポインタが無効になっている可能性が高いです。

クラッシュレポートからレジスタの内容を投稿したことがわかります。また、データの作成方法のコードを投稿してください(-[JUNSyncDocument initWithFileURL:]および-[NotefileAppDelegate documentForURL:].)

于 2013-04-12T22:21:18.810 に答える
1

代わりに使用していますが、まったく同じ問題があります( UIDocument&NSDocumentサブクラス、plistデータにアクセスするとクラッシュします) 。NSFileWrapper

マップされたファイル パスは、レポートで疑わしく見えます (OS によって匿名化されていない限り)。実際のファイルではなく、クエリ文字列のようです。NSMetadataQueryが間違った結果を返しているのではないですか?

私はこれまでのところ解決策がなく、まだ探しています。

アップデート

この問題を顧客と一緒にデバッグし、ログ情報を使用してカスタム ビルドを生成することができました。ここに私の観察があります:

  • クラッシュは、 、 、および他の多くのAPI などNSPropertyListSerialization、さまざまな API で発生します。CGImageSourceCreateWithURL
  • アクセスされたファイルはiCloudコンテナに保存されます

次のステータスがあります。

fileExists = YES;
isUbiquitous = YES;
hasNonZeroSize = YES;
isDownloaded = NO;

そのため、ほとんどの API では通常のファイルとして表示されますが、使用できません。アクセスすると、アプリがクラッシュします。- アクセスされたisDownloaded = YESファイル自体 (ファイル パッケージ内) にはisDownloaded = NO.

回避策:isDownloadedファイルの内容にアクセスする前に、ファイルのプロパティを確認してください。このプロパティは、次を使用してチェックされます。

-[NSURL getResourceValue:&val forKey:NSURLUbiquitousItemIsDownloadedKey error:&error]

私のようNSFileWrapperにコンテンツを読むために使用している場合は、次のUIDocumentチェックインが必要です。

-[UIDocument readFromURL:(NSURL *)url error:(NSError *__autoreleasing *)outError]

NSFileWrapper必要なファイル パッケージにアクセスできないためですNSURL

ドキュメントが作成されるときの iCloud の原子性に問題があると思われます。ドキュメント ディレクトリが最初に作成され、その内容が 2 つの異なる操作としてそこにコピーされた場合と同様に、ファイル パッケージとその内容がダウンロードされた状態で同期されていないようです。

于 2013-05-22T20:52:46.990 に答える