why does this code give EXC_BAD_ACCESS (using IMP)

不打扰是莪最后的温柔 提交于 2019-12-20 10:25:25

问题


This code gives me EXC_BAD_ACCESS, why?

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

I'm just starting using IMP, firs try.. no luck. Not sure why I get the error, also.. in the past, when I got EXC_BAD_ACCESS, the message was printed at the console, this time the error line is highlighted.

Some notes: ARC is enabled, XCode 4.3.2, the project uses Objective-C++ as de default language/compiler,this code is at the very beginning of the project

thanks guys


回答1:


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.




回答2:


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" );


来源:https://stackoverflow.com/questions/10952996/why-does-this-code-give-exc-bad-access-using-imp

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