【问题标题】:Strange Clang behaviour in Xcode 8.3Xcode 8.3 中奇怪的 Clang 行为
【发布时间】:2017-05-27 11:31:14
【问题描述】:

最近我注意到 Xcode 中 Objective C 内存管理的奇怪行为。 代码如下:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *firstString = [[NSString alloc] initWithString: @"Hello"];
        NSString *secondString = firstString;
        [firstString release];
        NSLog(@"%@", secondString);
    }
    return 0;
}

我认为,释放 firstString 后 secondString 指向 nil 并且 NSLog 应该会产生错误。 但是此代码不会产生任何错误并成功打印“Hello”字符串。 我用这样的命令手动编译和运行代码,也没有发现任何错误:

% clang -framework Foundation -fno-objc-arc main.m && ./a.out

我尝试使用在线 Objective-C 编译器 (GCC) (http://rextester.com/l/objectivec_online_compiler) 编译此代码,但出现错误。 我究竟做错了什么? ARC 支持在 Xcode 中被关闭。 提前致谢。

【问题讨论】:

    标签: ios objective-c xcode clang


    【解决方案1】:

    如果您执行静态分析(Xcode 中的 shift+command+B,或 Xcode 的“产品”菜单中的“分析”) ,它会警告你在对象被释放后你正试图引用它:

    问题在于,在手动引用计数代码中,您对已释放对象的引用不会自动设置为nil。因此,除非您手动 nil 这些指针,否则您最终可能会得到指向先前已释放的对象的悬空指针。

    静态分析器非常擅长识别这类问题等。我建议您在继续之前确保静态分析仪的健康状况良好。

    在这种情况下的第二道防线是启用僵尸运行时调试选项。这将报告在对象被释放后与对象交互的任何尝试。当您编辑 Xcode 目标的方案时,可以在“诊断”部分启用僵尸。

    不幸的是,您使用的是NSString,它不遵循典型的内存管理规则(它可以保留自己对字符串的引用,因此它们并不总是在您期望它们被释放时被释放)。

    考虑一个类似于你的例子,除了自定义类:

    #import <Foundation/Foundation.h>
    
    @interface MyObject: NSObject
    @end
    @implementation MyObject
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            MyObject *firstObject = [[MyObject alloc] init];
            MyObject *secondObject = firstObject;
            [firstObject release];
            NSLog(@"%@", secondObject);
        }
        return 0;
    }
    

    如果您在启动僵尸的情况下运行此程序,您将收到一条相应的错误消息,表明您正在尝试与已释放的实例进行交互:

    2017-05-27 08:19:18.154033-0700 MyApp[36888:7215135] *** -[MyObject isProxy]:消息发送到已释放实例 0x100303620

    但您可能不会收到来自NSString 的警告。最重要的是,应该避免从NSString 行为中得出任何更广泛的内存管理结论。相反,请依赖 Xcode 的静态分析器和僵尸程序。 (注意,当您完成应用程序的调试时,请记得关闭僵尸。)

    【讨论】:

    • 感谢您提供如此详细的回答!我尝试并得到了其他对象(不是 NSString)的预期行为。
    • NSString 因这种行为而臭名昭著。我不熟悉其他行为如此异常的人,但这是可能的。在不知道您遇到类似问题的其他课程的情况下,我无法进一步发表评论。但如果你听从静态分析器的建议,你会没事的。
    猜你喜欢
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多