简体   繁体   English

Objective-C运行时崩溃

[英]Objective-C runtime crash

I am trying out Objective-C runtime methods for the first time. 我第一次尝试使用Objective-C运行时方法。 I have been reading a chapter(24) on this from iOS 7 programming pushing the limits. 我一直在阅读iOS 7编程中有关这一极限的一章(24)。 As per the example in the book I have implemented a message dispatcher function which is as below: 按照本书中的示例,我实现了一个消息分发器功能,如下所示:

static const void *myMsgSend(id receiver, const char *name) {
    SEL selector = sel_registerName(name);
    Class receiverClass = object_getClass(receiver);
    IMP methodIMP = class_getMethodImplementation(receiverClass, selector);
    return CFBridgingRetain(methodIMP(receiver, selector));
}

I test this dispatcher in the function below: 我在以下函数中测试此调度程序:

void runMyMsgSend() {
    // NSObject *object = [[NSObject alloc] init];
    Class class = (Class)objc_getClass("NSObject");
    id object = class_createInstance(class, 0);
    myMsgSend(object, "init");

    // id description = [object description];
    id description = (__bridge id)myMsgSend(object, "description");

    // const char *cstr = [description UTF8String];
    const char *cstr = myMsgSend(description, "UTF8String");

    printf("---------------------");
    printf("%s\n", cstr);
}

The function works well for init and description for object instance of type NSObject . 该函数对于NSObject类型的对象实例的初始化描述非常有效。 When the dispatcher function is called on object pointed by description with UTF8String as the method to run it crashes on 在以UTF8String作为运行方法的描述指向的对象上调用分派器函数时,它崩溃

return CFBridgingRetain(methodIMP(receiver, selector)); 返回CFBridgingRetain(methodIMP(receiver,selector));

Now I know that NSString is a cluster and actually an object of __NSCFString is used. 现在我知道NSString是一个群集,实际上使用了__NSCFString的对象。 I think this may be the problem while calling CFBridgingRetain . 我认为这可能是调用CFBridgingRetain时出现的问题。 I need a better understanding of what is actually causing the crash. 我需要更好地了解真正导致崩溃的原因。 Thanks in advance. 提前致谢。

You are trying to call CFBridgingRetain on all return types.. 您正在尝试在所有返回类型上调用CFBridgingRetain

The documentation explicitly states that if the IMP returns anything that is NOT void , then you must explicitly cast it to the right function pointer type. 该文档明确指出,如果IMP返回的结果不是NOT void ,则必须将其明确转换为正确的函数指针类型。

Your function is: 您的功能是:

static const void *myMsgSend(id receiver, const char *name) {
    SEL selector = sel_registerName(name);
    Class receiverClass = object_getClass(receiver);
    IMP methodIMP = class_getMethodImplementation(receiverClass, selector);
    id (*imp)(id, SEL) = (id (*)(id, SEL))methodIMP;
    return CFBridgingRetain(imp(receiver, selector));
}

When you called UTF8String , it returns a const char* which you are trying to retain. 当您调用UTF8String ,它将返回您尝试保留的const char* Not only that, but you are saying that the IMP returns an id and you retain that.. You can only retain Objective-C class objects. 不仅如此,您还说IMP返回一个id然后保留该id 。您只能保留Objective-C类对象。 You never casted to the correct function pointer type so it crashes trying to implicitly convert const char* to id .. 您从未转换为正确的函数指针类型,因此尝试将const char*隐式转换为id时崩溃。

Therefore your method needs to be: 因此,您的方法需要为:

static const void *myMsgSend(id receiver, const char *name) {
    SEL selector = sel_registerName(name);
    Class receiverClass = object_getClass(receiver);
    IMP methodIMP = class_getMethodImplementation(receiverClass, selector);

    void* (*imp)(id, SEL) = (void* (*)(id, SEL))methodIMP;
    return imp(receiver, selector, args);
}

where it returns a simple void* which can be NULL or BOOL or int or w/e type (primitive).. If it needed to return an object, the object is implicitly bridged so no need to retain (just cast the result to the right type). 返回简单的void* ,该值可以为NULL或BOOL或int或w / e类型(原始)。如果需要返回对象,则该对象被隐式桥接,因此无需保留(只需将结果强制转换为正确的类型)。

However, it is probably a much better idea to use NSInvocation as the implementation of this function because then you don't have to worry about type and arguments and so on.. 但是,使用NSInvocation作为此函数的实现可能是一个更好的主意,因为这样您就不必担心类型和参数等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM