苹果官方关于内存管理的介绍(原文+翻译)(二)

简介: 苹果官方关于内存管理的介绍(原文+翻译)(二)

Memory Management Policy


内存管理策略



The basic model used for memory management in a reference-counted environment is provided by a combination of methods defined in the NSObject  protocol and a standard method naming convention. The NSObject class also defines a method, dealloc, that is invoked automatically when an object is deallocated. This article describes all the basic rules you need to know to manage memory correctly in a Cocoa program, and provides some examples of correct usage.


在引用计数环境下,内存管理使用的基本模型,是在NSObject协议中定义的方法和标准的方法命名规则的组合。NSObject类定义了一个方法,dealloc,它会在当一个对象被释放时自动调用。本文描述了您需要知道的所有基本规则,以便正确地管理Cocoa程序中的内存,并提供正确使用的一些示例。

#重点词汇
a combination of  …的组合


Basic Memory Management Rules


基本内存管理法则



The memory management model is based on object ownership. Any object may have one or more owners. As long as an object has at least one owner, it continues to exist. If an object has no owners, the runtime system destroys it automatically. To make sure it is clear when you own an object and when you do not, Cocoa sets the following policy:


内存管理模型基于对象所有权。任何对象都可能有一个或多个所有者。只要一个对象有至少一个所有者,它就会一直存在。如果一个对象没有了所有者,那么运行时系统就会自动销毁这个对象。为了明确您什么时候拥有一个对象,什么时候销毁一个对象,Cocoa制定了以下规则:


  • You own any object you create
  • 你拥有任何你创建的对象


You create an object using a method whose name begins with "alloc", "new", "copy", or "mutableCopy" (for example, alloc, newObject, or mutableCopy).

你使用以alloc、new、copy或mutableCopy为开始的名字来创建一个对象。(例如:alloc,newObject,mutableCopy)


  • You can take ownership of an object using retain
  • 你可以使用retain来获得一个对象的所有权


A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations:


(1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and


(2) To prevent an object from being invalidated as a side-effect of some other

operation (as explained in Avoid Causing Deallocation of Objects You’re Using).


接收到的对象通常被保证在它被接受到的方法内持续有效,并且这个这个方法也可以安全地将对象返回给它的调用者。你在以下两种情况下会使用retain:


(1) 在一个存取方法或者初始化方法的实现中,获得一个你想存储为属性值的对象的所有权。


(2) 在执行某些其它操作时,防止对象被作废。(正如在Avoid Causing Deallocation of Objects You’re Using一问中所述)


  • When you no longer need it, you must relinquish ownership of an object you own
  • 当你不再需要它时,你必须放弃你所拥有对象的所有权


You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.


你通过发送释放消息或自动释放消息来放弃一个对象的所有权。在Cocoa的术语中,放弃一个对象的所有权通常被称为“释放”一个对象。


  • You must not relinquish ownership of an object you do not own
  • 你无法放弃一个你所不拥有的对象的所有权


This is just corollary of the previous policy rules, stated explicitly.

这只是明确陈述了以上政策规则的推论。


重点词汇


A Simple Example


一个简单的例子



To illustrate the policy, consider the following code fragment:

为了阐述规则,请思考以下代码片段:

{
    Person *aPerson = [[Person alloc] init];
    // ...
    NSString *name = aPerson.fullName;
    // ...
    [aPerson release];
}


The Person object is created using the alloc method, so it is subsequently sent a release message when it is no longer needed. The person’s name is not retrieved using any of the owning methods, so it is not sent a release message. Notice, though, that the example uses release rather than autorelease.


Person对象是使用alloc方法创建的,所以随后当它不再被需要的时候会发送一个释放消息。Person对象的name没有用任何拥有的方法检索到,所以它不发送释放消息。注意,尽管如此,这个例子使用release而不是autorelease。

Use autorelease to Send a Deferred release


使用autorelease发送延迟释放



You use autorelease when you need to send a deferred release message—typically when returning an object from a method. For example, you could implement the fullName method like this:


当你需要发送一个延迟的释放消息时(通常当在一个方法中返回一个对象时),你会使用autorelease。例如,你可以像这样实现一个fullName方法:

- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName] autorelease];
    return string;
}


You own the string returned by alloc. To abide by the memory management rules, you must relinquish ownership of the string before you lose the reference to it. If you use release, however, the string will be deallocated before it is returned (and the method would return an invalid object). Using autorelease, you signify that you want to relinquish ownership, but you allow the caller of the method to use the returned string before it is deallocated.


你拥有alloc方法返回的字符串的所有权。为了遵守内存管理法则,你必须在失去这个字符串的引用之前放弃它。如果你使用release,那么这个字符串将会在返回之前被释放掉。(并且这个方法将会返回一个无效对象)使用autorealease,意味着你想要放弃这个字符串的所有权,但是允许方法的调用者在返回的字符串被释放之前使用它。

You could also implement the fullName method like this:

你也可以像这样实现fullName方法:

- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@",self.firstName, self.lastName];
    return string;
}


Following the basic rules, you don’t own the string returned by stringWithFormat:, so you can safely return the string from the method.

遵循基本规则,你不会拥有由stringWithFormat:方法返回的字符串,所以就可以安全地从方法返回字符串。


By way of contrast, the following implementation is wrong:

作为对比,以下的实现方式是错误的:

- (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",
                                         self.firstName, self.lastName];
    return string;
}


According to the naming convention, there is nothing to denote that the caller of the fullName method owns the returned string. The caller therefore has no reason to release the returned string, and it will thus be leaked.


根据命名规则,并没有表明fullName方法的调用者拥有返回的字符串。因此调用者没有理由释放返回的字符串,并且字符串将会因此被泄漏。


重点词汇


  • subsequently 其后,随后,接着; “subsequent”的派生; 嗣后; 尔后
  • retrieved 恢复; 取回( retrieve的过去式和过去分词 ); 寻回; 检索
  • deferred 延期的,缓召的; 拖延,延缓,推迟( defer的过去式和过去分
  • abide by 遵守; 信守; 忠于; 接受
  • relinquish 放弃; 让出; 放开,松手; 撤离
  • signify 意味; 预示; 表示…的意思; 具有重要性,要紧; 辱骂
  • By way of 路经; 途经; 作为; 意在
  • contrast 对比,对照; 差异; 对照物,对立面; 反差; 对比; 形成对照;
  • denote 代表; 指代; 预示; 意思是


You Don’t Own Objects Returned by Reference


你不会拥有引用返回的对象



Some methods in Cocoa specify that an object is returned by reference (that is, they take an argument of type ClassName ** or id *). A common pattern is to use an NSError object that contains information about an error if one occurs, as illustrated by initWithContentsOfURL:options:error: (NSData) and initWithContentsOfFile:encoding:error: (NSString).


Cocoa中的一些方法明确指出了对象是由引用返回的(那是因为他们携带了一个ClassName或者是id类型的参数)。常见的模式是如果发生错误使用包含错误信息的NSError对象,如NSData的initWithContentsOfURL:options:error:方法和NSString的initWithContentsOfFile:encoding:error:


方法所示。


In these cases, the same rules apply as have already been described. When you invoke any of these methods, you do not create the NSError object, so you do not own it. There is therefore no need to release it, as illustrated in this example:


在这些情况下,同样的规则应用已经被描述过了。当你调用这些方法时,你不创建NSError对象,所以你并不拥有它。因此无需释放它,如本例所示:

NSString *fileName = <#Get a file name#>;
NSError *error;
NSString *string = [[NSString alloc] initWithContentsOfFile:fileName
                        encoding:NSUTF8StringEncoding error:&error];
if (string == nil) {
    // Deal with error...
}
// ...
[string release];


Implement dealloc to Relinquish Ownership of Objects


实现dealloc来放弃对象的所有权



The NSObject class defines a method, dealloc, that is invoked automatically when an object has no owners and its memory is reclaimed—in Cocoa terminology it is “freed” or “deallocated.”. The role of the dealloc method is to free the object's own memory, and to dispose of any resources it holds, including ownership of any object instance variables.


NSObject类定义了一个方法,dealloc,当一个对象没有拥有者并且它的内存被回收(在Cocoa术语中叫“freed” 或者 “deallocated”),dealloc方法会被自动调用。dealloc方法的作用是释放对象拥有的内存,并且解决掉它拥有的任何资源,包括任何对象的实例变量。


The following example illustrates how you might implement a dealloc method for a Person class:


下面的例子解释了如何为一个Person类实现dealloc方法:

@interface Person : NSObject
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (assign, readonly) NSString *fullName;
@end
@implementation Person
// ...
- (void)dealloc
    [_firstName release];
    [_lastName release];
    [super dealloc];
}
@end


Important: Never invoke another object’s dealloc method directly.

不要直接调用另一个对象的dealloc方法。


You must invoke the superclass’s implementation at the end of your implementation.

你必须在你的实现的结尾调用父类的实现。


You should not tie management of system resources to object lifetimes; see Don’t Use dealloc to Manage Scarce Resources.

你不应该将系统资源的管理和对象的生命周期绑定在一起;参见Don’t Use dealloc to Manage Scarce Resources


When an application terminates, objects may not be sent a dealloc message. Because the process’s memory is automatically cleared on exit, it is more efficient simply to allow the operating system to clean up resources than to invoke all the memory management methods.

当一个应用程序终止时,对象可能不会发送dealloc消息。因为进程的内存在退出时会自动清除,允许操作系统清除资源比调用所有的内存管理方法更有效。


Core Foundation Uses Similar but Different Rules


Core Foundation 使用相似但不同的规则



There are similar memory management rules for Core Foundation objects (see Memory Management Programming Guide for Core Foundation). The naming conventions for Cocoa and Core Foundation, however, are different. In particular, Core Foundation’s Create Rule (see The Create Rule) does not apply to methods that return Objective-C objects. For example, in the following code fragment, you are not responsible for relinquishing ownership of myInstance:


Core Foundation 对象有着相似的内存管理规则(参见Memory Management Programming Guide for Core Foundation)然而Cocoa和Core Foundation有着不同的命名规则。尤其是Core Foundation的创建规则(参见 The Create Rule)不适用于返回OC对象的方法。例如,在下面的代码块中,你不负责放弃myInstance对象的所有权:

MyClass *myInstance = [MyClass createInstance];


重点词汇

  • invoke 乞灵,祈求; 提出或授引…以支持或证明; 召鬼; 借助
  • reclaimed 再生的; 回收的; 翻造的; 收复的; 开拓( reclaim的过去式
  • terminology 专门名词; 术语,术语学; 用辞
  • dispose of 解决; 将处理掉; 驳倒; 将吃光喝完
  • responsible for 为…负责,是造成…的原因
目录
相关文章
|
2月前
|
存储 安全 Java
jdk21的外部函数和内存API(MemorySegment)(官方翻译)
本文介绍了JDK 21中引入的外部函数和内存API(MemorySegment),这些API使得Java程序能够更安全、高效地与JVM外部的代码和数据进行互操作,包括调用外部函数、访问外部内存,以及使用不同的Arena竞技场来分配和管理MemorySegment。
71 1
jdk21的外部函数和内存API(MemorySegment)(官方翻译)
|
iOS开发
苹果官方关于内存管理的介绍(原文+翻译)(一)
苹果官方关于内存管理的介绍(原文+翻译)(一)
200 0
苹果官方关于内存管理的介绍(原文+翻译)(一)
|
JavaScript 前端开发 程序员
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
273 1
|
21天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
29天前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
1月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
22 3
|
1月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
49 1
|
1月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。