自动释放的对象何时真正释放?
Posted
技术标签:
【中文标题】自动释放的对象何时真正释放?【英文标题】:When is an autoreleased object actually released? 【发布时间】:2011-01-30 16:44:51 【问题描述】:我是 Objective-c 的新手,我正在尝试了解内存管理以使其正确。
在阅读了苹果的优秀Memory Management Programming Guide for Cocoa 之后,我唯一关心的是什么时候 实际上,自动释放的对象是在 iphone/ipod 应用程序中释放的。我的理解是在运行循环的末尾。但是什么定义了应用程序中的运行循环?
所以我想知道下面的代码是否正确。假设一个对象
@implementation Test
- (NSString *) functionA
NSString *stringA;
stringA = [[[NSString alloc] initWithString:@"Hello"] autorelease]
return stringA;
- (NSString *) functionB
NSString *stringB;
stringB = [self functionA];
return stringB;
- (NSString *) functionC
NSString *stringC;
stringC = [self functionB];
return stringC;
- (void)viewDidLoad
[super viewDidLoad];
NSString* p = [self functionC];
NSLog(@"string is %@",p);
@end
此代码有效吗?
从苹果的文字中,我了解到从 functionA 返回的 NSString 在 functionB 的范围内是有效的。我不确定它在 functionCtrong> 和 viewDidLoad 中是否有效。
谢谢!
【问题讨论】:
【参考方案1】:该代码没有任何问题。它将按照您的预期编译和运行。
从functionA
返回的NSString
对象在返回时仍然有效,因为它正在堆栈中向下传递给正在跟踪它的下一个人 (functionB
)。
【讨论】:
“向下传递堆栈”可能不是短语的最佳选择,因为它暗示堆栈用于返回值,但并非总是如此。【参考方案2】:是的,您的函数是有效的,并且使用正确的 Cocoa 约定来返回对象,用于保留/释放/自动释放/复制。
要回答关于什么是 runloop 的问题,在应用程序的 main() 函数中,它会调用 UIApplicationMain()。你可以想象 UIApplicationMain 看起来像这样:
void int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName)
UIApplication *app = /* create app using principalClassName */;
[app setDelegate:/* create delegate using delegateClassName */];
while (![app shouldTerminate])
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
event = [app getNextEvent];
[app dispatchEvent:event];
[pool drain];
while 循环类似于 UIKit 实际在执行的操作,并且每次通过该 while 循环就像一次通过 runloop,函数 getNextEvent 阻塞等待某个事件发生。您的所有方法通常都是从 dispatchEvent: 之类的内部调用的。您可以尝试在您的一个方法中设置断点,例如 IBAction,然后在顶部的调试器调用堆栈中查看处理事件和运行循环的 UIKit 方法的名称。由于您的每个方法都是从该 while 循环中调用的,因此每次对对象调用 autorelease 时,该对象都会添加到运行循环中的该外部池中。当当前事件完成分发时,池被清空,这些对象最终被发送释放消息。
最后一点。可以有不止一个自动释放池,它们并不总是在事件循环的末尾。有时,您可能会在整个事件循环中一次分配数万个对象。发生这种情况时,您可能会在自己的方法中设置额外的内部自动释放池,以减少自动释放池中自动释放对象的数量。自动释放池可以堆叠。
【讨论】:
我是否理解正确,如果我没有创建任何自动释放池,所有自动释放的变量都将保留在内存中,直到应用程序没有关闭? 类似,系统框架会在主线程堆栈的顶部以 UIApplicationMain() 等方法为您创建一些自动释放池。但是,如果您启动了自己的线程,并且没有创建池,那么是的,这些对象会泄漏。在这种情况下,自动释放方法会记录到控制台。 好的,谢谢,但是这很奇怪,通常的做法是使用返回自动释放对象而不释放它们的构造函数,但实际上与发生内存泄漏相同(分配了内存)直到申请结束)。还是我有什么不明白的地方? 由 UIApplicationMain 等函数为您创建的自动释放池每次通过事件循环时都会被耗尽一次。所以物体会很频繁地消失。如果您创建自己的线程,然后在该线程上创建自动释放对象,则需要定期排空并重置自动释放池。 好的,谢谢 Jon,现在说得通了,唯一的问题是我不太清楚这种情况下的事件循环是什么,你能举个事件的例子吗?以上是关于自动释放的对象何时真正释放?的主要内容,如果未能解决你的问题,请参考以下文章