为什么在使用objc运行时库中的class_replaceMethod调用函数时ARC会导致EXC_BAD_ACCESS?

时间:2014-12-18 04:12:39

标签: objective-c automatic-ref-counting hook objective-c-runtime method-swizzling

我需要替换某些特定Objective-C类的方法实现。 objc / runtime库中的一组函数能够做到这一点。为简化问题,我只需编写如下最简单的示例代码:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface MyClass : NSObject
- (void) func;
@end

@implementation MyClass

- (void) func {
    NSLog(@"Hello from MyClass!");
}

@end

//Original implementation of the method
static IMP gOriginalFunc = nil;

//Hook function that will take place of the original method
void HookFunc(id self, SEL _cmd)
{
    NSLog(@"[MyClass func] is hooked!");
    gOriginalFunc(self, _cmd);//EXC_BAD_ACCESS occurs here when ARC is enabled!!
}

int main(int argc, char *argv[])
{
    Class clsMyClass = objc_getClass("MyClass");
    // Restore the original method implementation:
    gOriginalFunc = class_getMethodImplementation(clsMyClass, @selector(func));
    Method mtdFunc = class_getInstanceMethod(clsMyClass, @selector(func));
    // Replace implementaion of the method of my own:
    class_replaceMethod(clsMyClass, @selector(func), IMP(HookFunc), method_getTypeEncoding(mtdFunc));
    objc_registerClassPair(clsMyClass);

    MyClass* obj = [[MyClass alloc] init];
    [obj func];

    return 0;
}

我只是替换[MyClass func]的原始实现。当设置编译器标志-fno-objc-arc时,此代码可以正常工作:

2014-12-18 11:59:17.524 Hooker[749:72783] [MyClass func] is hooked!
2014-12-18 11:59:20.361 Hooker[749:72783] Hello from MyClass!

但是启用ARC时会出现问题(通过将编译器标志设置为-fobjc-arc)。调用gOriginalFunc时抛出EXC_BAD_ACCESS信号(如注释所示)。我不知道原因,谁能说出来?

1 个答案:

答案 0 :(得分:1)

您的函数原型不准确,编译器错误地设置了调用。使用ARC,包括引用计数操作。要么是未定义的行为。

要更正程序,请通知编译器实际的功能签名,以免它搞砸了电话:

typedef void (*HookFunc_Signature)(id, SEL); // << != IMP's signature
static HookFunc_Signature gOriginalFunc = nil;

...后:

gOriginalFunc = (HookFunc_Signature)class_getMethodImplementation(clsMyClass, @selector(func));