IOS:NSString的发布没有按预期工作

Cod*_*der 9 iphone memory-management ios

我发现NSString有一个奇怪的行为.我试着运行下面的代码并注意到了这一点.

NSString *str = [[NSString alloc] initwithstring : @"hello"];
[str release];
NSLog(@" Print the value : %@", str);
Run Code Online (Sandbox Code Playgroud)

在这里,在第三行应用程序应该崩溃,因为我们正在访问一个被释放的对象.但它印刷了str的价值.它没有崩溃.但是对于NSArray,我观察到了不同的行为.

NSArray *array = [[NSArray alloc] initwithobjects : @"1",  @"2", nil];
[array release];
NSLog(@"Print : %@", [array objectatindex : 0]);
NSLog(@"Print : %@", [array objectatindex : 0]);
Run Code Online (Sandbox Code Playgroud)

该代码有两个用于NSArray的NSLog语句.在执行第一个NSLog后释放,这是打印值.但是当第二个NSLog被执行时,应用程序崩溃了.应用程序崩溃是可以接受的,因为访问的数组已经发布 但是当第一个NSLog执行时它应该崩溃.不是第二个.

帮助我解决这个问题.在这些情况下如何发布.

谢谢Jithen

rma*_*ddy 7

第一个示例不会崩溃,因为永远不会释放字符串文字.代码实际上是:

NSString *str = @"hello";
[str release];
Run Code Online (Sandbox Code Playgroud)

人们在内存管理上被字符串文字烧毁,并错误地==用来比较它们而不是isEqualToString:.编译器会进行一些导致误导结果的优化.

更新:

以下代码证明了我的观点:

    NSString *literal = @"foo";
    NSString *second = [NSString stringWithString:literal];
    NSString *third = [NSString stringWithString:@"foo"]; // <-- this gives a compiler warning for being redundant
    NSLog(@"literal = %p", literal);
    NSLog(@"second = %p", second);
    NSLog(@"third = %p", third);
Run Code Online (Sandbox Code Playgroud)

此代码提供以下输出:

2013-02-28 22:03:35.663 SelCast [85617:11303] literal = 0x359c
2013-02-28 22:03:35.666 SelCast [85617:11303] second = 0x359c
2013-02-28 22:03:35.668 SelCast [ 85617:11303]第三= 0x359c

请注意,所有三个变量都指向同一个内存.


Car*_*zey 6

您的第二个示例在第二个示例崩溃,NSLog因为在第一个日志中,array尚未重新使用的内存,但第一个日志导致堆上的足够活动导致内存被其他内容使用.然后,当您再次尝试访问它时,您会崩溃.

每当一个对象被释放并且其内存被标记为空闲时,就会有一段时间内该内存仍然存储该对象的剩余部分.在此期间,您仍然可以在这些对象上调用方法,而不会崩溃.这个时间非常短,如果你运行了很多线程,那么调用你的方法可能就不够了.显然,不要依赖这个实现细节来处理任何行为.

正如其他人所说,关于你的第一个问题,NSString文字不会被解除分配.对于其他一些基础类(NSNumber想到这一点)也是如此,但也是一个实现细节.如果您需要对内存管理进行实验,请使用NSObject实例,因为它不会显示异常行为.