我发现了NSString的奇怪行为。我试着运行下面的代码并发现了这一点。
NSString *str = [[NSString alloc] initwithstring : @"hello"];
[str release];
NSLog(@" Print the value : %@", str);
这里,在第三行应用程序应该崩溃,因为我们正在访问一个被释放的对象。但它印刷了str的价值。它没有崩溃。但是对于NSArray,我观察到了不同的行为。
NSArray *array = [[NSArray alloc] initwithobjects : @"1", @"2", nil];
[array release];
NSLog(@"Print : %@", [array objectatindex : 0]);
NSLog(@"Print : %@", [array objectatindex : 0]);
代码有两个用于NSArray的NSLog语句。在执行第一个NSLog后释放,这是打印值。但是当第二个NSLog被执行时,应用程序崩溃了。应用程序崩溃是可以接受的,因为访问的数组已经发布但是当第一个NSLog执行时它应该崩溃。不是第二个。
帮助我解决这个问题。在这些情况下,发布如何工作。
由于 Jithen
答案 0 :(得分:7)
第一个示例不会崩溃,因为永远不会释放字符串文字。代码真的是:
NSString *str = @"hello";
[str release];
人们在内存管理上使用字符串文字进行刻录,并错误地使用==
来比较它们而不是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);
此代码提供以下输出:
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] third = 0x359c
请注意,所有三个变量都指向同一个内存。
答案 1 :(得分:6)
您的第二个示例在第二个NSLog
崩溃,因为在第一个日志中,array
所在的内存尚未重复使用,但该第一个日志导致堆上的足够活动导致被其他东西使用的记忆。然后,当您再次尝试访问它时,会发生崩溃。
每当一个对象被释放并且其内存被标记为空闲时,就会有一段时间内该内存仍然存储该对象的剩余部分。在此期间,您仍然可以在这些对象上调用方法,而不会崩溃。这个时间非常短,如果你运行了很多线程,那么调用你的方法可能就不够了。显然,不要依赖这个实现细节来做任何行为。
正如其他人所说,关于你的第一个问题,NSString
文字不会被解除分配。对于其他一些基础课程(包括NSNumber
)也是如此,但也是一个实现细节。如果您需要对内存管理进行实验,请使用NSObject
实例,因为它不会显示异常行为。
答案 2 :(得分:4)
当您在对象上发送release
消息时,该对象实际上未从内存中删除。发布消息只是仅将引用计数减少一个。如果引用计数为零,则将对象标记为空闲。然后系统将其从内存中删除。在发生此解除分配之前,您可以访问您的对象。即使您release
对象,您的对象指针仍然指向对象,除非您将nil
指定给指针。
答案 3 :(得分:0)
第一个示例不会崩溃,因为永远不会释放字符串文字。第二种完全取决于释放和保留反击。
Read this article. Its contains short-and-sweet explanation for your query
答案 4 :(得分:0)
您似乎认为release
应立即销毁该对象。我不认为这是语言的保证。 release
的含义是:我已经完成了使用这个对象,我保证不再使用它。从那时起,系统决定何时实际释放内存。
除此之外,您看到的任何行为都未定义,可能会从Objective C运行时的一个版本更改为下一个版本。
这就是说,其他答案表明差异是字符串文字和内存的重复使用当前正确但假设行为总是这样,这可能是一个错误。< / p>