Xcode 8.3中的奇怪Clang行为

时间:2017-05-27 11:31:14

标签: ios objective-c xcode clang

最近我注意到在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;
}

我认为, secondString 在释放 firstString 后指向 nil 并且 NSLog 会产生错误。 但是这段代码不会产生任何错误并成功打印出#34; Hello&#34;串。 我使用这样的命令手动编译和运行代码,并没有发现任何错误:

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

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

1 个答案:

答案 0 :(得分:2)

如果在Xcode中执行静态分析( shift + 命令 + B ,或者在Xcode上执行&#34; Analyze&#34; #39; s&#34;产品&#34;菜单),它会警告您在对象发布后尝试引用该对象:

static analysis

问题在于,在手动引用计数代码中,您对已解除分配对象的引用是自动设置为import React, {Component} from 'react'; import ReactDOM from "react-dom"; var less = require('less'); var lessCss = require('./app.less'); console.log(lessCss); //output: /static/media/app.725ced4d.less less.render(lessCss, function (e, output) { console.log(e); //output: Unrecognized Input console.log(output); //output: undefined }); class Main extends Component { /* render functions */ 。因此,除非您手动nil这些指针,否则您最终可能会暂停指向先前已取消分配的对象的指针。

静态分析仪非常擅长识别这些类型的问题。在继续之前,我建议您确保从静态分析仪中获得清洁的健康状况。

在这种情况下的第二道防线是启用僵尸运行时调试选项。这将报告在取消分配对象后与对象进行交互的任何尝试。可以在&#34;诊断&#34;中启用僵尸。编辑Xcode目标计划时的部分。

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

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

NSString

如果您在僵尸打开的情况下运行此命令,则会收到相应的错误消息,指出您正在尝试与已解除分配的实例进行交互:

  

2017-05-27 08:19:18.154033-0700 MyApp [36888:7215135] *** - [MyObject isProxy]:消息发送到解除分配的实例0x100303620

但您可能无法从#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; } 收到此警告。最重要的是,应该避免从NSString行为中得出更广泛的记忆管理结论。相反,依靠Xcode的静态分析器和僵尸。 (注意,记得在你完成调试应用程序时关闭僵尸。)