简体   繁体   English

在Objective C中释放内存的最佳方法是什么?

[英]What is the best way to dealloc memory in Objective C?

I have a query regarding the memory management. 我有关于内存管理的查询。

Let's begin with an example. 让我们从一个例子开始吧。 Assume we have a class as follows. 假设我们有一个类如下。

@interface myClass : NSObject {
    NSString *xyz;
}
@end

Now, see the implementation. 现在,请参阅实施。

@interface myClass : NSObject {
    NSString *xyz;
}
@end

@implementation myClass
-(void)abc{
    // xyz allocted here
}
-(void)pqr{
    // retained or copied many times or may not a single time
}
-(void)mno{
    // retained or copied many times or may not a single time
}
-(void)jpg{
    // may be released more than one time or may be not
}


//-(void)dealloc{
//  [xyz release];
//  [super dealloc];
//}
//
//-(void)dealloc{
//  if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
//  [super dealloc];
//}

-(void)dealloc{
    if(xyz!=nil){ 
        while([xyz retainCount]>0) 
           [xyz release]; 
        xyz=nil; 
    }
    [super dealloc];
}
@end

In above code. 在上面的代码中。 I have three dealloc functions. 我有三个dealloc函数。 Which one is preferable? 哪个更好? If none of these, then please suggest yours. 如果没有这些,那么请建议你的。

I am confused because Objective C says, object must be released each time = each time alloc/retained. 我很困惑,因为Objective C说,每次都必须释放对象=每次分配/保留。

But most of the sample code has just single statement "[xyz release];" 但大多数示例代码只有单个语句“[xyz release];” doesn't it create a memory leak? 它不会造成内存泄漏吗?

This is absolutely wrong: 这是绝对错误的:

while([xyz retainCount]>0) 
       [xyz release]; 
    xyz=nil; 

retainCount will never return 0, because as soon as you are at a retainCount of 1 and the object is released, the runtime just deallocates it right then and there, never decrementing the retainCount . retainCount永远不会返回0,因为只要你在retainCount为1并且释放了该对象,运行时就会立即释放它,并且永远不会减少retainCount Even if it did decrement the retainCount, the object is now deallocated. 即使它确实减少了retainCount,该对象现在也被释放了。 How are you going to ask it what it's retainCount is? 你怎么会问它什么是retainCount?

In a nutshell, your design is wrong. 简而言之,您的设计是错误的。 If you can't keep track of how often you've retained an object in a smarter way, then you will have memory leaks and most likely crashes from overreleasing objects (this while loop will crash your app). 如果你无法跟踪你以更智能的方式保留对象的频率,那么你将会发生内存泄漏,并且很可能会因过度释放的对象而崩溃(这会导致应用程序崩溃)。

If you absolutely can't change your code (I wouldn't believe you if you said you couldn't), then you'd want to keep a second integer ivar indicating how many times you've retained xyz , and then use that to figure out how many times you should release it. 如果你绝对不能改变你的代码(如果你说你不能改变我就不相信你),那么你想保留第二个整数ivar,表明你保留xyz ,然后使用弄清楚你应该释放多少次。 (However, this should be an absolute last ditch effort, as in Armaggeddon will happen if you don't get this working in 30 seconds. You should really refactor your code first.) (但是,这应该是绝对的最后努力,因为如果你没有在30秒内完成这项工作,就会发生Armaggeddon。你应该首先重构你的代码。)

In addition, you've forgotten the call to [super dealloc] in your dealloc method. 另外,你忘记了dealloc方法中对[super dealloc]的调用。

- (void)dealloc {
    [xyz release];
    [super dealloc];
}

...is the correct version. ...是正确的版本。 In Objective-C, you generally shouldn't use the retainCount method. 在Objective-C中,通常不应使用retainCount方法。

If you want to be very safe, you can also write: 如果你想要非常安全,你也可以写:

- (void)dealloc {
    [xyz release], xyz = nil;
    [super dealloc];
}

The idea is that myClass has a member variable (in your case, xyz). 我的想法是myClass有一个成员变量(在你的情况下,xyz)。 When a myClass object gets created, it should create (or get a reference to) xyz by adding only 1 to the retain count (whether through retain or other means depends on the situation). 当创建myClass对象时,它应该通过仅向保留计数添加1来创建(或获取对xyz的引用)(无论是通过保留还是其他方式取决于具体情况)。

It would not be a good idea in each method to retain xyz with releasing it again. 在每种方法中保留xyz并再次释放它不是一个好主意。 So at the end of each method, the the local object should have no more holds on xyz than it had at the beginning of the method. 因此,在每个方法的最后,本地对象应该在xyz上没有比在方法开头时更多的保留。

By the time dealloc gets called, only that single retain hold should remain on xyz (as far as the myClass object is concerned), so a single call to release will suffice. 当dealloc被调用时,只有那个单独的保留保持应该保留在xyz上(就myClass对象而言),因此单次调用release就足够了。 It is not a good idea to release until the retainCount is zero because another object somewhere might be using it. 在retainCount为零之前释放不是一个好主意,因为某个地方的另一个对象可能正在使用它。

To directly answer your question, use this dealloc: 要直接回答您的问题,请使用此dealloc:

-(void)dealloc{
    [xyz release];
}

objects those are retained during the poperty declaration need to be released in the dealloc method. 在poperty声明期间保留的对象需要在dealloc方法中释放。 So if you are declaring 所以,如果你要宣布

@property(nonatomic, retain)NSString xyz; ,

you need it to be released in dealloc as 你需要它以dealloc发布为

-(void)dealloc{
    [xyz release];
    [super dealloc]
}

Any other allocated memory should be released immediately after the last use of that object from within your methods. 应该在方法中最后一次使用该对象后立即释放任何其他已分配的内存。

So if you are allocating xyz, in 所以,如果你要分配xyz,in

-(void)abc{
    // xyz allocted here
}

then you shoud release it at the end of the same method. 那么你应该在同一个方法结束时释放它。

-(void)abc{
    // xyz allocted here
// do something with xyz

//release xyz

example: 例:

        -(void)abc{
           xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
        // do something with xyz


    [xyz release]  

  //release xyz

In this case you need not release it in the dealloc method. 在这种情况下,您无需在dealloc方法中释放它。

Also not that if you are property declaring xyz and retining it, you should not allocate it in your methods nor should release 同样不是如果你是声明xyz并对其进行修饰的属性,你不应该在你的方法中分配它,也不应该释放它

    while([xyz retainCount]==0) 
       [xyz release]; 

Should be > 0 , otherwise the -release is not executed. 应该> 0 ,否则不执行-release Even so, deallocating xyz like this is a bad practice because xyz may be still owned by someone else. 即便如此,像这样解除分配xyz是一种不好的做法,因为xyz可能仍然由其他人拥有。

You should allocate xyz one and only one time, and if you -copy it to replace xyz , always -release the old one. 您应该分配xyz有且仅有一个时间,如果你-copy它来代替xyz ,总是-release旧的。 Always follow the Cocoa memory management rule. 始终遵循Cocoa内存管理规则。

If you really need to adopt multiple ownership to xyz , and a separate integer ivar to record how many times you have retained xyz , so you have the correct number to -release in -dealloc . 如果你真的需要对xyz采用多个所有权,并且需要一个单独的整数ivar来记录你保留xyz ,那么你在-dealloc有正确的数字来-release

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM