テーブルビューのスクロールで落ちることがある件の調査
もうずいぶん前に報告もらってるんだけど未解決。再現することは確認したのでもっと早く直せると思ったのですが手こずっています。
前のメモが見つからなかったので今日の作業を記録。
現象
- NSTableViewをスクロールしているとEXC_BAD_ACCESSで落ちる
- 必ず起きるという手順は見つかっていないが、スクロールを繰り返すとほぼ再現する
調査
デバッグシンボル付きのRubyCocoaでやってみる。落ちたときのログはこんな感じ。
Exception Type: EXC_BAD_ACCESS (SIGABRT) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000d29 Application Specific Information: objc[29757]: garbage collection is OFF abort() called Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fff95ecfce2 __pthread_kill + 10 1 libsystem_c.dylib 0x00007fff947e87d2 pthread_kill + 95 2 libsystem_c.dylib 0x00007fff947d9a7a abort + 143 3 libruby.1.dylib 0x0000000108c9c649 rb_bug + 316 4 libruby.1.dylib 0x0000000108d03d8c 0x108c89000 + 503180 5 libsystem_c.dylib 0x00007fff9483acfa _sigtramp + 26 6 libruby.1.dylib 0x0000000108cd046a rb_obj_is_kind_of + 175 7 com.apple.rubycocoa 0x0000000108c55fcb ovmix_ffi_closure + 491 (OverrideMixin.m:143) 8 libffi.dylib 0x00007fff9746c7ea ffi_closure_unix64_inner + 510 9 libffi.dylib 0x00007fff9746bffe ffi_closure_unix64 + 70 10 com.apple.AppKit 0x00007fff8f2fe11b -[NSTableView _dataSourceValueForColumn:row:] + 73 11 com.apple.AppKit 0x00007fff8f2fdb9b -[NSTableView preparedCellAtColumn:row:] + 437
RubyCocoaのコードはframework/src/objc/OverrideMixin.mのovmix_ffi_closure()のrb_obj_is_kind_of()が問題のよう。
138 if (!ocdata_to_rbobj(Qnil, args_octypes[i - 2], args[i], &arg, NO)) 139 rb_raise(rb_eRuntimeError, "Can't convert Objective-C argument #%d of octype '%s' to Ruby value", i - 2, args_octypes[i - 2]); 140 141 OVMIX_LOG("converted arg #%d of type '%s' to Ruby value %p", i - 2, args _octypes[i - 2], arg); 142 *143* if (!NIL_P(arg) 144 && rb_obj_is_kind_of(arg, objid_s_class()) == Qtrue 145 && !OBJCID_DATA_PTR(arg)->retained) { 146 OVMIX_LOG("retaining %p", OBJCID_ID(arg)); 147 [OBJCID_ID(arg) retain]; 148 OBJCID_DATA_PTR(arg)->retained = YES; 149 OBJCID_DATA_PTR(arg)->can_be_released = YES; 150 }
argはVALUEで、手前でocdata_to_rbobj()で用意した値。さすがにrb_obj_is_kind_of()/CLASS_OF()に問題があるとは思えないので、このocdata_to_rbobj()で取ってきたVALUEがおかしいってことなんだと思う。となると、
あたりかなと考えている。可能性が高そうなのは前者だけど、どうやって調べたものか。