ios 内存管理

截止今日,copy apple 开发网一句话:Objective-C provides two methods of application memory management.见下面两条:

1 “manual retain-release” or MRR, you explicitly manage memory by keeping track of objects you own. This is implemented using a model, known as reference counting, that the Foundation class NSObject provides in conjunction with the runtime environment.

2 In Automatic Reference Counting, or ARC, the system uses the same reference counting system as MRR, but it inserts the appropriate memory management method calls for you at compile-time. You are strongly encouraged to use ARC for new projects.

简要概述:

第一种是MRR(其实采用的就是reference counting);

第二种是ARC(这个其实还是使用了类似MRR的reference counting system,只不过在编译时,在合适的地方插入的内存管理的方法调用);

apple建议我们采用第二种,但这样会依赖于其编译器的代码插入。

本文主要分析MRR内存管理

我们一定一定要注意:在非ARC下,编译器是不会自动插入内存管理代码的,举例:

{
    Person *aPerson = [[Person alloc] init];
    // ...
    //The person’s name is not retrieved using any of the owning methods, so it is not sent a release message.
    NSString *name = aPerson.fullName;
    // ...
    //The Person object is created using the alloc method, so it is subsequently sent a release message when it is no longer needed.
    [aPerson release];
    //在我理解,如果在这时再访问name,是会出问题的(这都调用release方法了,肯定是MRR内存管理,而非ARC)
}

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. 

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:

  • You own any object you create

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

  • You can take ownership of an object using 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).

  • 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. 

  • You must not relinquish ownership of an object you do not own

Use autorelease to Send a Deferred release

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:

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

1 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. 

2 If you use release, however, the string will be deallocated before it is returned (and the method would return an invalid object). 

3 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.

当然了,我们还可以使用其他办法来实现这个函数,比如:

- (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.

深入分析一下,看看下面这个这种实现方式有什么问题:

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.

简要分析:这样的实现并不是说程序就一定会crash,而是可能产生内存leak。如果调用者释放了这个string,那么ok,理论上来说,没有问题。但是话又说回来,调用者怎么知道:我要不要释放这个string呢?如果调用者不释放,那么就是内存泄露。能自己干的事,千万不要把这种问题留给调用者。

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).

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:

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];
再讨论下dealloc方法的怎么使用:

Implement dealloc to Relinquish Ownership of Objects

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.

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

@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.

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.

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.


事情总不会那么完美,后续还有啥:

Core Foundation Uses Similar but Different Rules

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:

MyClass *myInstance = [MyClass createInstance];

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值