简体   繁体   English

将对象设置为nil时不调用dealloc方法

[英]dealloc method is not invoked when set an object to nil

I have a question. 我有个问题。

I first created an object which extends NSObject, I provided overrides for the description and dealloc methods. 我首先创建了一个扩展NSObject的对象,我提供了描述和dealloc方法的覆盖。 Here's my Employee.m file: 这是我的Employee.m文件:

@implementation Employee
.....

-(NSString *)description
{
    return [NSString stringWithFormat:@"Employ ID: %d has $%d value of assets", [self     employeeID], [self valueOfAssets]];
}

-(void)dealloc
{   
    NSLog(@"deallocating.. %@", self);
    [super dealloc];
}

In my main.m, I first created an NSMutableArray to hold a list of Employee objects: 在我的main.m中,我首先创建了一个NSMutableArray来保存Employee对象列表:

NSMutableArray *employees = [[NSMutableArray alloc] init];

for (int i =0; i< 10; i++)
{
    // Create an instance of Employee
    Employee *person = [[Employee alloc] init];

    // Give the instance varaible interesting values
    [person setEmployeeID:i];
    [employees addObject: person];
}

and at the end I set employees to nil 最后我把员工定为零

employees = nil;

I expected the dealloc method of each Employee object to be called and I would see some logs like: 我期望调用每个Employee对象的dealloc方法,我会看到一些日志,如:

deallocating.. Employ ID 0 has value.....
deallocating.. Employ ID 2 has value.....
....

However, I didn't see any logs and if I set a breakpoint on the dealloc method, the breakpoint is never hit. 但是,我没有看到任何日志,如果我在dealloc方法上设置断点,则断点永远不会被命中。

Any thoughts? 有什么想法吗?

A couple of observations: 几点意见:

  1. person = nil does not release an object in non-ARC code. person = nil不会在非ARC代码中释放对象。 It will in ARC code (at least if it's strong). 它将在ARC代码中(至少如果它很强大)。

  2. In ARC, local objects will be released for you automatically when they fall out of scope. 在ARC中,当本地对象超出范围时,它们将自动为您释放。 In non-ARC, objects falling out of scope will not be released for you (and if you don't have other references to those objects elsewhere, you'll end up with a leak). 在非ARC中,不会为您释放超出范围的对象(如果您在其他地方没有其他对这些对象的引用,则最终会泄漏)。

  3. Adding an item to a mutable array will increase the retain count of the item, so even if you include a release in your non-ARC code, the object won't be released until the retain count drops to zero (accomplished by not only releasing the person objects after you add them to the array, but also removing them from the array. 将项添加到可变数组将增加项的保留计数,因此即使您在非ARC代码中包含一个版本,该对象也不会被释放,直到保留计数降至零(不仅仅通过释放来完成)将对象添加到数组后,也将对象从数组中删除。

Thus, given that this is non-ARC code, it could be something like: 因此,鉴于这是非ARC代码,它可能是这样的:

- (void)testInNonArcCode
{
    NSMutableArray *employees = [[NSMutableArray alloc] init]; // employees retain count = +1

    for (int i =0; i< 10; i++)
    {
        //create an instance of Employee
        Employee *person = [[Employee alloc] init]; // person retain count = +1

        //Give the instance varaible interesting values
        [person setEmployeeID:i];
        [employees addObject: person];  // person retain count = +2
        [person release];  // person retain count = +1 (YOU REALLY WANT TO DO THIS OR ELSE OR NON-ARC PROGRAM WILL LEAK)
        // person = nil;   // this does nothing, except clears the local var that's limited to the for loop scope ... it does nothing to reduce the retain count or improve memory management in non-ARC code, thus I have commented it out
    }

    // do whatever you want

    [employees removeAllObjects]; // this will remove all of the person objects and they will have their respective retain counts reduced to 0, and therefore the Employee objects will be released

    [employees release]; // employees array's own retain count reduced to zero (and will now be dealloced, itself)
}

In ARC code: 在ARC代码中:

- (void)testInArcCode
{
    NSMutableArray *employees = [[NSMutableArray alloc] init]; // employees retain count = +1

    for (int i =0; i< 10; i++)
    {
        //create an instance of Employee
        Employee *person = [[Employee alloc] init]; // person retain count = +1

        //Give the instance varaible interesting values
        [person setEmployeeID:i];
        [employees addObject: person];  // person retain count = +2

        // person = nil;      // this would reduce person retain count to +1 (but unnecessary in ARC because when person falls out of scope, it will have it's retain count automatically reduced)
    }

    // do whatever you want

    [employees removeAllObjects]; // this will remove all of the person objects and they will have their respective retain counts reduced to 0, and therefore will be released

    // [employees release]; // not permitted in ARC
    // employees = nil;     // this would effectively release employees, but again, not needed, because when it falls out of scope, it will be released anyway
}

The proper way of freeing objects is to do 解放对象的正确方法就是这样做

[employees release];

Setting it to nil will not release the memory. 将其设置为nil将不会释放内存。

By virtue of you being allowed to call [super dealloc] , I can assume that you are not using Automatic Reference Counting . 由于您被允许调用[super dealloc] ,我可以假设您没有使用自动引用计数 This means that you need to explicitly pair every alloc you write with a balancing release call. 这意味着您需要显式地将您编写的每个alloc与平衡release调用配对。 For you, when you make the array nil, you essentially leaked all of the memory for the employees. 对于你来说,当你使数组为零时,你基本上泄露了员工的所有内存。 You need to loop over the array again to release them all, or better yet since you are learning... Start as soon as possible writing ARC code. 您需要再次遍历数组以释放它们,或者更好,因为您正在学习... 尽快开始编写ARC代码。

It may be important to note that ARC was created for exactly this kind of situation; 值得注意的是,ARC是针对这种情况而创建的; it makes sense to our brains, and now it can be a reality if you use the latest tools. 它对我们的大脑有意义,现在如果你使用最新的工具它可以成为现实。

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

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