高效编写代码的方法(二十四):异常捕获中的内存管理

Exceptions

Exceptions(异常)在C++中和Objective-C中都有大量使用,并且异常对于两者都是兼容的,因此在C++中抛出的异常可以在Objective-C中进行处理,反之亦然。
在OC中,对于特别重大的错误,我们会抛出一个异常;其他方面比如很多第三方库都会有这些异常处理,系统的库也会有异常抛出。

Exceptions带来的内存问题

当涉及到内存管理的时候,如果异常捕获代码写的不当,就会造成内存泄漏。
比如以下这段代码:

    @try {
        SomeClass *object = [[SomeClass alloc] init];
        [object doSomethingMayThrow];
        [object release];
    } @catch (NSException *exception) {
        NSLog(@"出错啦!");
    }

当一个对象在@try中的block中被retain了,而在该对象被release之前如果有异常抛出,比如上面那样,[object release]就根本不会执行,而直接跳转到@catch block。那么除非在@catch中妥善处理,否则该对象就泄漏了。而且万一这个泄露的对象是一个data管理类的对象,那么他所持有的对象都会一起泄露,后果非常严重。

MRC中的解决办法

将上面代码处理成这样就没问题了:

        SomeClass *object;
    @try {
        object = [[SomeClass alloc] init];
        [object doSomethingMayThrow];
    } @catch (NSException *exception) {
        NSLog(@"出错啦!");
    } @finally {
        [object release];
    }

不过涉及到的对象或者异常捕获逻辑非常多,复杂的话,手动释放这些可能泄露的对象是非常乏味,而且容易遗漏。

ARC

在ARC中我们不能调用release方法,这时候该怎么处理这样的泄露情况呢?
默认情况下,这时候ARC也不会帮我们处理内存泄露。但是我们可以在compiler flag中打开-fobj-arc-exception选项来帮助我们完善在exception中的内存管理。


-fobj-arc-exception

但是这样带来的后果就是在runtime会加入大量的管理对象的代码,用来监测并及时清除掉这些在exception中泄露的对象。后果就是增加打包体积。
但是一般来说当异常被抛出的时候,我们的App也应该停止运行了,此时对象造成的泄露也会随着整个App的销毁而不存在,所以打开这个选项其实是不太符合使用规范的。

其实以上这些知道就行,因为实际上也并不需要我们做过多的干预。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容