4

最終更新:この問題の修正は気のめいるものであることが判明しました。プロジェクト内の.xcodeprojディレクトリに移動し、<username>.mode1v3および <username>.pbxuserファイルを削除します。それはそれを修正しました。ブー、Xcode。


これは、通常の保持/解放のバグではないということから始めます。それは私のコードの開発ブランチで発生し始めたばかりで、バグはマスターブランチには存在せず、答えを示すソースの違いを見つけるのに問題があります。だから私はただひどいものに行きます。

ビューコントローラクラスがあります。他のいくつかのViewControllerを参照するいくつかのプロパティがあります。それぞれは、次のように、必要に応じてゲッターアクセサーを介してロードされます。

- (NotesViewController *)notesViewController {
    if (notesViewController == nil) {
        notesViewController = [[NotesViewController alloc] initWithNibName:@"NotesViewController" bundle:nil];
    }
    return notesViewController;
}

後で電話するとき[self notesViewController]、それはすべて良いです。ただし、これは機能しなくなりました。

- (DateFieldController *)dateFieldController {
    NSLog(@"made it into the method at least ...");
    if (dateFieldController == nil) {
        NSLog(@"nib loader, don't let us down...");
        dateFieldController = [[DateFieldController alloc] initWithNibName:@"DateFieldController" bundle:nil];
    }
    return dateFieldController;
}

このメソッドが他のアクセサーと同じ方法で呼び出されると、明らかにnibのロード中ですが、おそらくその前に爆撃されます。

2010-07-08 11:44:58.029 MyApp[24404:207] made it into the method at least ...
2010-07-08 11:44:58.030 MyApp[24404:207] nib loader, don't let us down...
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) bt
#0  0x028bb0ca in _class_isInitialized ()
#1  0x028b9eca in _class_initialize ()
#2  0x028bf1f6 in prepareForMethodLookup ()
#3  0x028b86c9 in lookUpMethod ()
#4  0x028b8836 in _class_lookupMethodAndLoadCache ()
#5  0x028c6ad3 in objc_msgSend ()
#6  0x00007bb3 in -[EntryViewController controllerForFieldType:] (self=0x7942d70, _cmd=0x190c20, type=0x79844b0) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/EntryViewController.m:481
#7  0x00007e07 in -[EntryViewController selectTypesControllerDidSelect:] (self=0x7942d70, _cmd=0x190bb4, type=0x79844b0) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/EntryViewController.m:527
#8  0x0000d2ad in -[TypesViewController tableView:didSelectRowAtIndexPath:] (self=0x5d2aac0, _cmd=0x1eac458, aTableView=0x6056000, indexPath=0x781c780) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/TypesViewController.m:81
#9  0x0059e718 in -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] ()
#10 0x00594ffe in -[UITableView _userSelectRowAtIndexPath:] ()
#11 0x002abcea in __NSFireDelayedPerform ()
#12 0x0274cd43 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#13 0x0274e384 in __CFRunLoopDoTimer ()
#14 0x026aad09 in __CFRunLoopRun ()
#15 0x026aa280 in CFRunLoopRunSpecific ()
#16 0x026aa1a1 in CFRunLoopRunInMode ()
#17 0x02fd02c8 in GSEventRunModal ()
#18 0x02fd038d in GSEventRun ()
#19 0x0053ab58 in UIApplicationMain ()
#20 0x00001e24 in main (argc=1, argv=0xbffff050) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/main.m:14
(gdb)

nib loadメソッドを起動すると、SimulatorSDKで何か厄介なことが起こっているように見えます。実際、おそらくずっと早いです。の小さなNSLogアクションでnibloadinginitializerをオーバーライドすると、DateFieldController疑わしいことにどこにも行き着きません。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    NSLog(@"come on, you...");
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) 
    {
    NSLog(@"rock on!");
  }
  return self;
}

言うまでもなく、これらのNSLogステートメントはどちらも実行されません。

どうしたの?なぜランタイムが私を怒鳴りつけているのですか?(呼び出しをからself.dateFieldControllerに切り替えてもバグは修正され[self dateFieldController]ません。このコードは、クラッシュしていないマスターブランチのコードとまったく同じです)。

FWIW、XCode 3.2.3 64ビットでビルドしており、Simulator 4.0、Debug、i386 arch(OSX10.6.3を実行している新しいMacBookPro上)用にコンパイルしています。プロジェクト設定の展開ターゲットは「iPhoneOS」に設定されています。 3.0 "(これを3.1.3にアップグレードしても修正されません)。

更新:controllerForFieldType:要求に応じて、 :の実装

- (id)controllerForFieldType:(Type *)type {
    id controller = nil;

    if ([type.mode isEqualToString:@"note"]) {
        controller = self.notesViewController;
    } else if ([type.mode isEqualToString:@"date"]) {
        NSLog(@"going for it, attempting to load dateFieldController from accessor...");
        controller = self.dateFieldController;
    } else {
        controller = self.fieldViewController;
    }

    return controller;
}

特に関連性がないと思うので、これを以前に省略しました。問題は、スタックの後半、実際のゲッターメソッドで発生しているようdateFieldControllerです。

アップデートII: @zneakの提案で、[実行]-> [Guard Mallocを有効にする]の設定をオンにして、シナリオを再度実行しました。結果は基本的に同じですが、ランタイムの内部バックトレースが異なります。クラスまたはNIBに問題があり、デコードが妨げられているように見えます。

2010-07-08 12:26:26.180 Strip[24961:207] made it into the method at least ...
2010-07-08 12:26:26.289 Strip[24961:207] nib loader, don't let us down...
Program received signal:  “EXC_BAD_ACCESS”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Not safe to call dlopen at this time.)
(gdb) bt
#0  0x028cd41f in attachMethodLists ()
#1  0x028cdf77 in realizeClass ()
#2  0x028cedad in _class_getNonMetaClass ()
#3  0x028c8eb0 in _class_initialize ()
#4  0x028ce1f6 in prepareForMethodLookup ()
#5  0x028c76c9 in lookUpMethod ()
#6  0x028c7836 in _class_lookupMethodAndLoadCache ()
#7  0x028d5ad3 in objc_msgSend ()
#8  0x00007b81 in -[EntryViewController controllerForFieldType:] (self=0x38cfaf30, _cmd=0x190c8f, type=0x3cacbfe0) at /Users/wgray/Documents/Sources/iPhone/strip-iphone/Classes/EntryViewController.m:482
...snip...
#22 0x00001de4 in main (argc=1, argv=0xbfffefec) at /Users/wgray/Documents/Sources/iPhone/strip-iphone/main.m:14
(gdb)

アップデートIII:プロットが厚くなります。コメントの@ohorobの提案で、env arg OBJC_PRINT_INITIALIZE_METHODS = YESを追加したところ、ここで問題になっているものを除いて、アプリ内のすべてのクラスの初期化が適切であることがわかりました。コンソール出力では、それぞれが次のようになります。

objc[26750]: INITIALIZE: calling +[UIPinchGestureRecognizer initialize]
objc[26750]: INITIALIZE: finished +[UIPinchGestureRecognizer initialize]
objc[26750]: INITIALIZE: UIPinchGestureRecognizer is fully +initialized

アプリを実行して爆発につながるテーブル行を選択すると、クラッシュ前のnslogコンソール出力とクラッシュ自体が表示されます。これは、不適切な初期化を除外できることを意味すると思いますが、実行時の専門家ではありません。

masterブランチとこのdevブランチのコードの違いを徹底的に監査しましたが、まだポインターを踏んだことを示すものは何も見つかりませんでしたが、それが起こっている可能性が最も高いと思います。

4

2 に答える 2

2

クラスの初期化中に何かがおかしくなっています。

環境変数をYESに設定しOBJC_PRINT_INITIALIZE_METHODSて、アプリケーションを実行してみてください。それは私たちに手がかりを与えるかもしれません。か否か。(Xcodeの実行可能インスペクターで環境変数を設定します。ドキュメントを参照してください)。

方法はあります+initializeか?(どのクラスでも、クラスの1つが、クラッシュとは無関係に見える何かの初期化をくすぐっている可能性があります)

于 2010-07-08T17:19:30.010 に答える
1

問題が動き続けているという事実は、ランタイムの内部クラスデータ構造に何かが踏みにじられているのではないかと私に思わせます。私が最初に疑うのは、賢すぎるクラスでしょう。isaでゲームをするクラスはありませんか?この例については、XMPPMessage.mを参照してください。これらのビューコントローラクラスがisaで動作するかどうかは尋ねていません。これを間違えると、驚くべき方法でメモリを踏みにじる可能性があるため、システム内のどのクラスも意味します。

次に、class_copyMethodList()を使用して、+allocを呼び出す前にクラッシュするかどうかを確認します。もしそうなら、あなたのクラステーブルは間違いなく破損しています。

于 2010-07-08T18:45:40.103 に答える