原文地址:cachecrew.com/memory-mana…
原文作者:cachecrew.com/
发布时间:2011年5月
应用程序正确的内存管理是应用程序稳定性的关键。如果做得不正确,会导致无数的坏事发生!其副作用包括破坏应用程序数据,使应用程序崩溃,锁定计算机或设备的使用,甚至使系统崩溃或导致系统崩溃。副作用可能包括破坏应用程序数据,使应用程序崩溃,锁定计算机或设备的使用,甚至使系统崩溃或导致系统重启。 因此,内存管理问题总是在每个程序员的脑海里(如果不幸的话,也会在脑海里),特别是当他们学习一门新语言时。本文介绍了与内存管理有关的编程问题。在下一篇文章中,我将更多地介绍iOS/CocoaTouch视图控制器编程中的最佳内存管理实践,以提高技术含量。
在旧的、允许内存分配的程序化编程语言(非基于对象的语言,如C或Pascal)中,管理内存是非常直接的。
int appFunction(int size)
{
int *array = malloc(size * sizeof(int));
⋮
free(array); // Done with the dynamically allocated memory
} // appFunction()
例子。C语言的内存分配。
在面向对象编程中,应用程序设计者倾向于将他们的设计结构为对象的流畅交互。面向对象语言(如C++或Objective-C)的语法帮助程序员比程序化语言更容易避免内存管理错误,尤其是在更复杂的应用设计中。
由于Objective-C是与iOS和Mac OS X等环境所使用的API和框架一起发明的,所以苹果公司假定它的使用有一个类的层次结构,而且,就所有实际目的而言,它依赖于NSObject基类。这个类决定了整个游戏规则,与Objective-C语言本身几乎没有区别,所以如果没有NSObject,几乎不值得讨论Objective-C的使用。 虽然它看起来很复杂,但重要的是,分配和去分配是在代码中众所周知的位置处理的,这些位置将被用于其他目的,初始化器和去初始化器。
– (id)init:(int) size
{
self = [super init];
if (self)
_array = [[NSArray alloc] init];
return self;
} // -init
⋮
– (void)dealloc
{
[_array release];
[super dealloc]; // Done with the dynamically allocated memory
} // -dealloc
例子: Objective-C内存处理
就像在C语言中,你需要在内部确定什么时候应该调用malloc()和free()一样,在Objective-C语言中,你应该在内部确定 "对象所有权 "以及什么时候发送保留和释放消息。这些保留/释放消息(发送消息类似于函数或方法调用,在其他语言中)实现了引用计数--一种跟踪有多少对象在引用该对象的方法。
内化这个规则:如果你对一个对象进行了分配、保留或复制,你就拥有它,你的工作就是释放它......否则它就不是。
在Objective-C中,对象为它的使用或其他对象的使用分配其他对象。这些分配就是内存分配。Cocoa(在Mac OS X中使用)和CocoaTouch(在iOS中使用的Cocoa变体)编程框架假定对谁拥有一个对象有一个清晰的理解。任何数量的对象都可以保留另一个对象的所有权,无论是显式还是隐式。如果一个对象分配了另一个对象,那么该对象就有一个隐性的所有权。
stringOwner隐式拥有被分配的对象,所以它必须释放它。
NSString *stringOwner = [[NSString alloc] init];
⋮
[stringOwner release];
tempString不会获得所有权,但它可以在方法的持续时间内使用它。
NSString *tempString = [NSString string];
stringOwner已经通过retain索取了所有权,所以它必须释放它。
NSString *stringOnwer = [[NSString string] retain];
⋮
[stringOwner release];
如果一个对象被作为参数传递给另一个方法,那么另一个方法有可能会要求拥有这个对象。在这种情况下,发送者(也就是其他语言中的 "caller")可以在以后不需要对象时释放它。
NSString *stringOnwer = [[NSString string] retain];
⋮
[existingArray addObject:stringOwner]; // array is also, now, an owner
⋮
[stringOwner release]; // Not needed by this method (or class any longer)
问题是,尽管苹果公司有一套简单的规则(或者,更好的是,经验法则),但往往不清楚他们的API中哪些保留了传入对象的所有权,即使阅读官方文档也是如此。我通常会发现,如果我不确定,我需要在谷歌上搜索--这往往会导致来自Stack Overflow的最可靠的建议。
苹果公司一定知道这一点,因为他们提供了他们优秀的(虽然不完美)Instruments工具,与他们的Xcode开发环境一起工作,以帮助找出内存错误和泄漏。
下一步,我将写关于内存使用的文章,因为它涉及到iOS CocoaTouch视图控制器(因为这也是非常明显的)。
资源 - 基础知识
- 应用程序接口
- 程序化编程语言
- 面向对象的编程语言
- 参考计数
- 软件编程框架。
- 苹果的内存管理编程指南。 或者更好的是,内存管理,经验法则。
- Stack Overflow! 高质量的用户贡献帮助论坛。
通过www.DeepL.com/Translator(免费版)翻译