NSInvocation在获取返回值后crash问题
2016-04-06 13:07
169 查看
转载自: http://blog.csdn.net/zengconggen/article/details/38024625
在使用NSInvocation的过程中,遇到一个问题。那就是在获取返回结果后,app很快crash。示例如下:
[html] view
plain copy
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对象。
[html] view
plain copy
NSArray * __unsafe_unretained tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = tempResultSet;
或者
[html] view
plain copy
void *tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = (__bridge NSArray *)tempResultSet;
在使用NSInvocation的过程中,遇到一个问题。那就是在获取返回结果后,app很快crash。示例如下:
[html] view
plain copy
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对象。
[html] view
plain copy
NSArray * __unsafe_unretained tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = tempResultSet;
或者
[html] view
plain copy
void *tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSArray *resultSet = (__bridge NSArray *)tempResultSet;
相关文章推荐
- POJ2104 K-th Number 主席树
- MySQL relay_log_purge=0 时的风险
- Matlab实现线性回归和逻辑回归: Linear Regression & Logistic Regression
- 动态规划之最少硬币
- C语言 有/无符号数 需要注意的问题
- 唯品会RPC服务框架与容器化演进(转)
- 在android中通过java层程序调用命令行的一些备注
- HDU 4514并查集判环+最长路
- C#最简单最完整的webservice实例
- 团队简介
- Ubuntu中MySQL中文乱码解决
- 电脑莫名其妙的被装上了流氓软件DNSunlocker的解决办法
- TCP/UDP常见端口参考
- 解决切换Fragment出现卡顿的问题
- bzoj 3211: 花神游历各国 树状数组
- 细说Executor框架(下)
- 注册团队博客地址
- bzoj4491 我也不知道题目名字是什么
- 运算符优先级
- 统计学习方法——CART, Bagging, Random Forest, Boosting