why does this code give EXC_BAD_ACCESS (using IMP)

后端 未结 2 1498
温柔的废话
温柔的废话 2021-02-03 13:44

This code gives me EXC_BAD_ACCESS, why?

NSMutableDictionary  *d = [[NSMutableDictionary alloc] init];
IMP imp= [d methodForSelector:@selector(setObject:forKey:)          


        
相关标签:
2条回答
  • 2021-02-03 14:23

    The problem is that IMP has a return type of "id" which ARC will attempt to manage. You need to cast your function pointer to have a return type of void (consistent with the method you are calling):

        NSMutableDictionary  *d = [[NSMutableDictionary alloc] init];
        IMP imp= [d methodForSelector: @selector(setObject:forKey:)];
        void (*func)(__strong id,SEL,...) = (void (*)(__strong id, SEL, ...))imp;
        func( d,  @selector(setObject:forKey:), @"obj", @"key" );
    
    0 讨论(0)
  • 2021-02-03 14:27

    You need to cast the function pointer properly or ARC doesn't know what it's supposed to be doing. IMP is a generic function pointer that takes an id, a selector and a variable number of other, undefined arguments and returns an id. The method implementation you're trying to call takes an id, a selector followed by exactly two id parameters and has a void return type. You can fix it by changing to the following code:

    NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
    void (*imp)(id, SEL, id, id) = (void(*)(id,SEL,id,id))[dict methodForSelector:@selector(setObject:forKey:)];
    if( imp ) imp(dict, @selector(setObject:forKey:), @"obj", @"key");
    

    You should always check that you actually got a function pointer back before you dereference it, as that would also crash. The code above will work even in an ARC environment. Also, even when you're not using ARC, you should always cast your function pointers to the actual prototype rather than IMP. You should never use IMP. Other places that would cause major issues are if the method returns a struct or if the method takes floating point parameters, etc.

    Good habit: always cast your function pointers or make typedefs for them if you find the function pointer syntax jarring.

    0 讨论(0)
提交回复
热议问题