首页 > 解决方案 > Xcode Memory Graph 报告释放对象的泄漏

问题描述

Xcode 调试内存图工具已检测到释放可可对象的泄漏,如下面的代码所示。基本上,只要在分配可可对象的块中捕获异常,就会发生这种情况。您可以尝试使用任何 sdk,这里是 macOS 11.1,尽管 iOS 14.4 sdk 会产生相同的结果。您可以在对象范围结束后添加断点并启动 Debug Memory Graph 以查看泄漏的 NSString 对象。你怎么看,实际上是一个错误或错过了什么?

@interface TestClass : NSObject

- (void)testMethod;

@end

@implementation TestClass

- (void)testMethod {
    @try {
        NSMutableString *string = [NSMutableString new];
        NSLog(@"%p: %@", string, string);
        @throw [NSException exceptionWithName:@"exception1" reason:@"exception1" userInfo:nil];
    } @catch(NSException *exception) {
        NSLog(@"%@", exception);
    }
}

- (void)dealloc {
    NSLog(@"dealloc method called!");
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        {
            TestClass *testClass = [[TestClass alloc] init];
            [testClass testMethod];
        }
        NSLog(@"byebye");
    }
    return 0;
}

控制台输出:

0x1006a6330: whatever
exception1
dealloc method called!
byebye

问题导航器窗格中的泄漏对象摘要

LeakTest - 11521 Group
Memory Issues - (2 leaked types) Group
runtime: Memory Issues - (2 leaked types): 1 instance of __NSCFString leaked
    0x1006a6330
runtime: Memory Issues - (2 leaked types): 1 instance of CFString (Storage) leaked
    0x1006a63a0

快速查看上下文菜单项中泄露的 CFString 对象的内容

po [(NSString *)0x1006a6330 debugDescription]
whatever

标签: iosxcodecocoamemory-leaksmemory-graph-debugger

解决方案


这是预期的行为。在大多数情况下,ARC 不是异常安全的。可以通过传递来开启 ARC 的异常处理-fobjc-arc-exceptions(在 Objective-C++ 中默认开启),但它的成本很高。Objective-C 异常不打算用作通用错误处理机制(例如 Swiftthrows或 C++ 异常)。如ARC 文档的例外部分所述

标准的 Cocoa 约定是异常表示程序员错误并且不打算从中恢复。默认情况下使代码异常安全将对通常实际上不关心异常安全的代码施加严重的运行时和代码大小惩罚。因此,ARC 生成的代码默认会在异常情况下泄漏,如果进程无论如何都将立即终止,这很好。关心从异常中恢复的程序应该启用该选项。

有关 Objective-C 中标准错误处理模式的信息,请参阅处理Objective-C 编程中的错误。


推荐阅读