__bridge、out parameter使用不当引起的BAD_ACCESS错误
来源:互联网 发布:jquery数据交互 编辑:程序博客网 时间:2024/04/29 02:23
一. 表现
Thread 1: EXC_BAD_ACCESS(code=EXC_I386_GPFLT)
二. 复现
1.__bridge
CFAttributedStringRef attributedString = (__bridge CFAttributedStringRef)([[NSAttributedString alloc] initWithString:text]);CTLineRef line = CTLineCreateWithAttributedString(attributedString);
2.out parameter
- (void)checkZeroInArray:(NSArray <NSNumber *> *)array error:(NSError **)error { [array enumerateObjectsUsingBlock:^(NSNumber * _Nonnull number, NSUInteger index, BOOL * _Nonnull stop) { if (number.integerValue == 0) { if (error) { *error = [NSError errorWithDomain:@"" code:100 userInfo:nil]; } *stop = TRUE; } }];}...NSError *error = nil;[self checkZeroInArray:numbers error:&error];if (error) { NSLog(@"Error: %@", error); // EXC_BAD_ACCESS错误}
三. 错误分析
1.__bridge
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
如果你创建了一个对象,而没有指针指向它,这个对象会被立即回收,否则会造成内存泄露。这里情况类似,CFAttributedStringRef不受ARC管理,(__bridge T) op
修饰符的说明中有There is no transfer of ownership, and ARC inserts no retain operations.
, 而[[NSAttributedString alloc] initWithString:text]
受ARC管理,持有Ownship,需要负责管理内存,所以调用release方法回收了对象。
解决办法:
CFAttributedStringRef attributedString = (__bridge_retained CFAttributedStringRef)([[NSAttributedString alloc] initWithString:text]);CTLineRef line = CTLineCreateWithAttributedString(attributedString);...CFBridgingRelease(attributedString);
让CFAttributedStringRef own起这个对象,并由其负责释放。所以别忘记使用完之后调用CFBridgingRelease
。
2.out parameter
out parameter是一个函数向调用方返回数据的一种特殊方式(普通方式是将数据作为函数返回值返回)。
如果这个数据是个对象,并且是在函数当中创建的,就需要考虑它的内存管理问题。因为是我创建的,我拥有Ownship,但又不能像局部变量一样在作用域结束时release掉,因为作为返回值它要‘活出’作用域(穿透边界),对于函数返回值,一般我们采用的是autorelease的方式,达到既做到balance又穿透边界的平衡。
out parameter也是一样,编译器会把函数签名自动变成.... error:(NSError *__autorelease *)error
。这意味你要返回给调用方的对象是autorelease的。也就意味这这个对象会在autoreleasepool drain的时候被回收掉,正常情况下没有问题,在drain之前调用方已经结束对返回值的使用,或者retain了它。
但是在这个示例里面,enmuerateKeysAndObjectsUsingBlock会把block放入 @autoreleasepool { <#statements#> }
中执行,意味着你新创建的NSError对象在循环结束的时候就被回收了,造成BAD_ACCESS错误。
解决办法:
- 修改签名为
...error:(NSError *__strong *)error
- 在循环外面创建一个NSError的引用,用户指向新创建的NSError,然后赋值给out parameter.
四.参考文档
- https://stackoverflow.com/questions/14854521/where-and-how-to-bridge
- https://mp.weixin.qq.com/s/IybnvL7IOxcaVwr2GE1i3Q
- http://tutuge.me/2016/04/30/autoreleasing-meet-autoreleasepool/
- http://blog.pioneeringsoftware.co.uk/2012/03/06/out-parameters-when-arcing/
- __bridge、out parameter使用不当引起的BAD_ACCESS错误
- 指针使用不当引起断错误
- UIPopover使用不当引起的crash解决
- ABMultiValueCopyLabelAtIndex使用不当引起的内存泄漏
- ABMultiValueCopyLabelAtIndex使用不当引起的内存泄漏
- Hashset 使用不当引起的内存泄漏
- StringBuffer使用不当,引起的性能问题
- 记一次switch使用不当引起的错误,是哥粗心了哈。。。
- IIS配置不当引起的0x80004005错误解决方法
- 检测由new/delete使用不当引起的内存泄露
- 检测由new/delete使用不当引起的内存泄露
- Android中Handler使用不当引起的内存泄露
- __bridge的相关使用
- 美容产品使用不当引起“汞”中毒
- samba设置不当引起的广播风暴
- 项目发布操作不当引起的问题
- Https证书校验不当引起的安全问题
- MySQL的int设置不当引起BUG
- 计数排序
- Queue on Bus Stop CodeForces
- 做一个爱分享的工程师
- RE:JAVA学习-循环应用和数组
- Java移位操作、位运算详解
- __bridge、out parameter使用不当引起的BAD_ACCESS错误
- 集合(一)Collection
- 百练2819:W的密码题解
- 指针、内存操作中的一些其它注意点
- oracle undo segments, do blocks
- 用哈希算法的思想解决排序和字符串去重问题,时间复杂度为O(N)
- Matrx的数学原理
- Toastr消息提示框的使用
- PYTHON机器学习实战——集成学习 AdaBoost元算法