NSInvocation在獲取返回值後crash問題

在使用NSInvocation的過程中,遇到一個問題。那就是在獲取返回結果後,app很快crash。示例如下:

  NSMethodSignature *methodSignature = [FlightOperations instanceMethodSignatureForSelector:NSSelectorFromString(action)];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];

    [invocation setTarget:fOps];
    [invocation setSelector:NSSelectorFromString(action)];
    [invocation setArgument:&flightPoint atIndex:2];

    NSArray *resultSet;
    [invocation invoke];
    [invocation getReturnValue:&resultSet];

    return resultSet;

在設置Enable Zombies後發現,是由於系統多次釋放NSArray * resultSet造成的非法內存訪問。

原因是在arc模式下,getReturnValue:僅僅是從invocation的返回值拷貝到指定的內存地址,如果返回值是一個NSObject對象的話,是沒有處理起內存管理的。而我們在定義resultSet時使用的是__strong類型的指針對象,arc就會假設該內存塊已被retain(實際沒有),當resultSet出了定義域釋放時,導致該crash。假如在定義之前有賦值的話,還會造成內存泄露的問題。

解決辦法:

使用一個unretain的對象來獲取返回值,或者 用void *指針來保存返回值,然後用__bridge來轉化爲OC對象。

NSArray * __unsafe_unretained tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = tempResultSet;

或者

void *tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = (__bridge NSArray *)tempResultSet;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章