Ios Xcode 8.3中奇怪的叮当声行为

Ios Xcode 8.3中奇怪的叮当声行为,ios,objective-c,xcode,clang,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 *secondStr

最近我注意到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;
}
我试图用在线objective-c编译器(GCC)()编译这段代码,但出现了错误。 我做错了什么? 在Xcode中关闭ARC支持。
提前感谢。

如果您执行静态分析(在Xcode中执行shift+命令+B,或在Xcode的“产品”菜单上执行“分析”),它将警告您在对象释放后尝试引用该对象:

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

静态分析器非常擅长识别这些问题。我建议在继续之前,确保您有一份来自静态分析器的干净健康清单

在这种情况下,第二道防线是启用zombies运行时调试选项。这将报告在对象被释放后与对象交互的任何尝试。当您编辑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;
}
#导入
@接口MyObject:NSObject
@结束
@实现MyObject
@结束
int main(int argc,const char*argv[]{
@自动释放池{
MyObject*firstObject=[[MyObject alloc]init];
MyObject*secondObject=firstObject;
[第一对象释放];
NSLog(@“%@”,第二个对象);
}
返回0;
}
如果在启用zombies的情况下运行此操作,您将收到一条相应的错误消息,指示您正在尝试与解除分配的实例交互:

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


但您可能无法从
NSString
获得此警告。总之,应该避免从
NSString
行为中得出任何更广泛的内存管理结论。相反,依赖Xcode的静态分析器和僵尸。(请注意,调试完应用程序后,请记住关闭僵尸。)

感谢您提供如此详细的答案!我尝试了其他对象(不是NSString)的预期行为。
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;
}