7

这段代码给了我 EXC_BAD_ACCESS,为什么?

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

我刚开始使用 IMP,首先尝试.. 没有运气。不知道为什么我会收到错误,也..过去,当我收到 EXC_BAD_ACCESS 时,在控制台上打印了消息,这次错误行被突出显示。

一些注意事项:ARC已启用,XCode 4.3.2,项目使用Objective-C++作为de默认语言/编译器,此代码在项目的最开始

多谢你们

4

2 回答 2

21

您需要正确转换函数指针,否则 ARC 不知道它应该做什么。IMP 是一个通用函数指针,它接受一个 id、一个选择器和可变数量的其他未定义参数并返回一个 id。您尝试调用的方法实现需要一个 id,一个选择器后跟两个 id 参数,并且返回类型为 void。您可以通过更改为以下代码来修复它:

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

在取消引用之前,您应该始终检查您是否确实获得了函数指针,因为这也会崩溃。上面的代码甚至可以在 ARC 环境中工作。此外,即使您不使用 ARC,您也应该始终将函数指针转换为实际原型而不是 IMP。你永远不应该使用 IMP。其他会导致主要问题的地方是该方法是否返回一个结构或该方法是否采用浮点参数等。

好习惯:如果你发现函数指针语法不和谐,总是转换你的函数指针或为它们制作 typedef。

于 2012-06-08T17:26:45.373 回答
1

问题是 IMP 的返回类型为“id”,ARC 将尝试对其进行管理。您需要将函数指针转换为具有 void 的返回类型(与您正在调用的方法一致):

    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" );
于 2012-06-08T17:36:24.340 回答