2016-05-25 5 views
0

method_setImplementation()がNSObjectクラスのdeallocメソッドを置き換えていて、別のスレッドで同じ時刻にNSObjectインスタンスが呼び出している、またはdeallocメソッドを呼び出すとどうなりますか。はmethod_setImplementation()atomicですか?

インスタンスは正しいアドレスdeallocを取得しますか? メソッドswizzlingを使用するとランダムなクラッシュが発生します。また、deallocメソッドを呼び出すと常にクラッシュします。ここで

は私のクラッシュ情報です:

Exception Type: EXC_BAD_ACCESS (SIGBUS) 
Exception Codes: 0x00000000 at 0x0000000000000000 

とクラッシュしたスレッド:

Thread 0: 
0 libsystem_kernel.dylib   0x00000001837b7ffc 0x18379c000 + 114684 (__psynch_rw_unlock + 8) 
1 libsystem_pthread.dylib   0x0000000183881b1c 0x183880000 + 6940 (pthread_rwlock_unlock + 380) 
2 libobjc.A.dylib     0x000000018328f718 0x18327c000 + 79640 (<redacted> + 20) 
3 libobjc.A.dylib     0x00000001832894a0 0x18327c000 + 54432 (method_setImplementation + 64) 
4 MyApp       0x0000000100904824 0x1000b4000 + 8718372 (kszombie_install + 204) 
5 MyApp       0x0000000100448248 0x1000b4000 + 3752520 (-[DYCrashReportManager configureAdvancedSettings] + 60) 
6 MyApp       0x000000010044756c 0x1000b4000 + 3749228 (+[DYCrashReportManager setDefaultKSCrashHander] + 100) 
7 MyApp       0x00000001000e15b4 0x1000b4000 + 185780 (-[AppDelegate application:didFinishLaunchingWithOptions:] + 700) 
8 UIKit       0x0000000188dde8a8 0x188d54000 + 567464 (<redacted> + 400) 
9 UIKit       0x000000018900e094 0x188d54000 + 2859156 (<redacted> + 2904) 
10 UIKit       0x0000000189012500 0x188d54000 + 2876672 (<redacted> + 1684) 
11 UIKit       0x000000018900f674 0x188d54000 + 2864756 (<redacted> + 168) 
12 FrontBoardServices    0x00000001855bf7ac 0x185598000 + 161708 (<redacted> + 36) 
13 FrontBoardServices    0x00000001855bf618 0x185598000 + 161304 (<redacted> + 168) 
14 FrontBoardServices    0x00000001855bf9c8 0x185598000 + 162248 (<redacted> + 56) 
15 CoreFoundation     0x0000000183bd5124 0x183af4000 + 921892 (<redacted> + 24) 
16 CoreFoundation     0x0000000183bd4bb8 0x183af4000 + 920504 (<redacted> + 540) 
17 CoreFoundation     0x0000000183bd28b8 0x183af4000 + 911544 (<redacted> + 724) 
18 CoreFoundation     0x0000000183afcd10 0x183af4000 + 36112 (CFRunLoopRunSpecific + 384) 
19 UIKit       0x0000000188dd7834 0x188d54000 + 538676 (<redacted> + 460) 
20 UIKit       0x0000000188dd1f70 0x188d54000 + 515952 (UIApplicationMain + 204) 
21 DuoYiIM       0x00000001000c4300 0x1000b4000 + 66304 (main + 132) 
22 libdyld.dylib     0x000000018369a8b8 0x183698000 + 10424 (<redacted> + 4) 

Thread 2 Crashed: 
0 (null) 0x0000000000000000 0x0 + 0 
1 CoreFoundation     0x0000000183b01f14 0x183af4000 + 57108 (<redacted> + 148) 
2 libobjc.A.dylib     0x000000018329dae8 0x18327c000 + 137960 (<redacted> + 508) 
3 Foundation      0x00000001846dc844 0x184500000 + 1951812 (<redacted> + 1028) 
4 libxpc.dylib     0x00000001838b4b4c 0x1838b0000 + 19276 (<redacted> + 28) 
5 libxpc.dylib     0x00000001838b4af0 0x1838b0000 + 19184 (<redacted> + 40) 
6 libdispatch.dylib    0x000000018366947c 0x183668000 + 5244 (<redacted> + 16) 
7 libdispatch.dylib    0x00000001836754c0 0x183668000 + 54464 (<redacted> + 864) 
8 libdispatch.dylib    0x000000018366cf80 0x183668000 + 20352 (<redacted> + 464) 
9 libdispatch.dylib    0x000000018366947c 0x183668000 + 5244 (<redacted> + 16) 
10 libdispatch.dylib    0x0000000183677914 0x183668000 + 63764 (<redacted> + 2140) 
11 libdispatch.dylib    0x00000001836770b0 0x183668000 + 61616 (<redacted> + 112) 
12 libsystem_pthread.dylib   0x0000000183881470 0x183880000 + 5232 (_pthread_wqthread + 1092) 

私はNULLポインタを得ました。

deallocメソッドを置き換える安全な方法はありますか?

+1

libobjc.dylibのシンボルに関するスタックトレースの情報を修正することは、まったく役に立ちません。これらのアドレスを何か役に立つものにすることは絶対にありません。 –

+0

@ Richard J. Ross III.私のクラッシュレポートを取得するためにKSCrashを使用します。クラッシュするたびに、x1レジスタに 'dealloc'という文字列があります。つまり、システムはdeallocメソッドを呼び出していました。メソッドswizzling、しかし、私は正確な理由を知らない。私はおそらくmethod_setImplementation()はアトミックではないので、私は助けに来た疑いがあります。 – zuik

答えて

2

objc実行時の操作方法はですが、一般的にはアトミックですが、アトミック性はスレッドセーフではありません。スレッドスレッドBが前記オブジェクトを使用している間にオブジェクトの実装に絡むと、スレッドBが新しい実装か古い実装を使用するかどうかが保証されないという点で、常に危険です。 NSObjectののメソッドをスウィズル

全体的には、しかし、 スウィズリング方法が悪い

悪いです。

+0

ARCの下ではスウィズルのdeallocもうまく定義されていますか?私は、クラスが直接定義していないときにコンパイラがそのほとんどを最適化したと考えました。 –

+1

@RobNapier Yup;私は、スウィージングを使ってdeallocを手放すことは、ARCの下でより深く穴を掘る可能性が高いと思うが、壊れていないとは思わない。私。基本的にどの方法もモジュール間の境界から呼び出すことができるため、ARCは常に非ARCと互換性がなければならず、その逆もあります。 – bbum

0

私のクラッシュの理由を見つけると思います。 これは、KSCrashがゾンビオブジェクトを検出する方法をdeallocに変更したためです。それはinstallDealloc_NSObject()で、method_setImplementation()は、実装を変更しましたが、オブジェクトがdeallocを呼び出し、別のスレッドで同じ瞬間にg_originalDealloc_NSObject yet.Andに古い実装を返すいなかったので、handleDealloc_NSObject()にするとき

static IMP g_originalDealloc_NSObject; 
static void handleDealloc_NSObject(id self, SEL _cmd) 
{ 
    handleDealloc(self); 
    typedef void (*fn)(id,SEL); 
    fn f = (fn)g_originalDealloc_NSObject; 
    f(self, _cmd); 
} 
static void installDealloc_NSObject() 
{ 
    g_originalDealloc_NSObject = method_setImplementation(class_getInstanceMethod([NSObject class], @selector(dealloc)),(IMP)handleDealloc_NSObject); 
} 

クラッシュが起こりましたヌルポインタエラーが発生しました。

関連する問題