一次方法执行引起的"血案"

最近在研究函数调用performSelector的时候遇到下面的问题:

WechatIMG13

  • 有参数为返回值
  id perfromSele  = [self performSelector:@selector(performSelectorS:arg2:) withObject:@"第一个参数" withObject:@"第二个参数"];
    if (perfromSele) {
        NSLog(@"打印结果为===%@",perfromSele);
    } else {
        NSLog(@"没有返回值");
    }

    - (void )performSelectorS:(NSString *)args1 arg2:(NSString *)args2 {
    NSLog(@"performSelectorS args1 %@   args2 %@",args1,args2);
}
  • 无参数无返回值

WechatIMG721

 id returnValue = [self performSelector:@selector(testReturnValueMethod)];
    if (returnValue) {
        NSLog(@"returnValue===%@",returnValue);
    } else {
        NSLog(@"returnValue ==没有返回值");
    }
    - (void)testReturnValueMethod { 
    // 这个时候打开注释会闪退
    //    NSLog(@"this is method");

    }

神奇的一幕发生了:有参数有返回值的时候。当传入第一个参数为字符串的时候,返回值perfromSele 为__NSCFConstantString 当第一个参数不为string 的时候,返回值为0x0 也就是说没有返回值。无参数无返回值的时候,如果执行的方法里有代码用返回值接收。会闪退。如果执行方法里什么都不写,那么正常执行返回值为0x0。

一位搞逆向的朋友告诉我说:这是汇编的问题,他是这样解释的:

(汇编问题)原因应该是performSelector的returnvalue为0x0, 当执行方法里面为空的时候,没有改变寄存器的地址。所以0x0在PerformSelector的时候地址还为0x0.如果方法里面调用堆栈的时候,最后导致0x0不能被access所以就报bad access错误了。
comments powered by Disqus