why does this code give EXC_BAD_ACCESS (using IMP)

≡放荡痞女 提交于 2019-12-02 21:15:41

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.

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" );
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!