没有明确调用Objective-C版本

bar*_*rit 4 iphone cocoa objective-c ios

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    

NSString * str = [[NSString alloc] initWithString:@"test"];
[str release];
int i = 999999999;
while(i-- > 0) {}
NSLog(@"%@", str);
[pool drain];
Run Code Online (Sandbox Code Playgroud)

输出:测试

为什么不release工作?如何立即从内存中删除对象?

Xcode 4.0版iPhone应用程序


〜求助〜

感谢大家的答案.我有很多关于这个问题的有用信息.我将使用NSString*str = @"text"而不是NSString*str = [[NSString alloc] initWithString:@"text"];

我知道释放只是"标记"记忆"愿意被释放",但不能立即释放它

Joe*_*Joe 6

发布确实有效,但您尝试执行的操作具有未定义的行为,并且在使用NSString和文字时,您可能也会遇到不同的行为.发生的事情是,虽然您的对象被释放,但该位置的内存可以回收并且没有更改,当它打印时它仍然有效.由于它是NSString,因此不一定要发送描述消息,这就是为什么在尝试发送解除分配的对象时没有获得异常的原因.

这个问题有一些关于NSString和NSLog的好信息.

  • 提及字符串文字的+1可以区别对待.使用+ numberWithInt:创建的NSNumber实例有时可以以相同的方式运行,返回当人们可能天真地假设时未解除分配的实例.重要的是正确平衡自己的记忆管理 - 不要关注窗帘背后的男人! - 并且OP正确地做到了. (3认同)

BJ *_*mer 6

它确实有效.您已放弃该对象的所有权,并且当系统确定它不再拥有时,系统将标记为可供系统重用.如果您是该字符串的唯一所有者,那可能会立即发生.如果字符串的创建导致它在内部自动释放,则可能会在稍后的某个时间点发生.或者,正如Dave DeLong指出的那样,系统可能会将其优化为永不释放的对象.

在您的情况下,它被优化为一个常量字符串,它将在程序的生命周期中存在.如果你使用的是一个NSMutableString而不是一个NSString,你会看到可能不会崩溃的时髦行为,但不会打印你所期望的.(请参阅此问题以获取示例.)

如果你使用了一个NSArray,它在你调用时被释放release,但你仍然会看到你的NSLog示例正常工作,直到你分配了一些其他对象.释放只是将内存标记为可重用; 它实际上并没有清除它.因此,如果您将数组传递给NSLog,则该内存尚未更改,因此仍可正确打印.

但是,所有这一切的关键点是要认识到调用release不一定会导致对象被释放.它可能因任何原因而继续存在.但是一旦你打电话release,你就放弃了对象的所有权.如果你在那之后继续使用它,系统可以自由地做各种奇怪的事情,如图所示.