dealloc-methode wordt niet aangeroepen wanneer een object op nul wordt gezet

Ik heb een vraag.

Ik heb eerst een object gemaakt dat NSObject uitbreidt, ik voorzag in overschrijvingen voor de beschrijving en dealloc-methoden. Hier is mijn Employee.m-bestand:

@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 mijn main.m heb ik eerst een NSMutableArray gemaakt om een ​​lijst met Employee-objecten te houden:

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];
}

en aan het einde heb ik de werknemers op nul gezet

employees = nil;

Ik verwachtte dat de methode dealloc van elk object Employee zou worden aangeroepen en dat ik enkele logboeken zou zien als:

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

Ik heb echter geen logboeken gezien en als ik een onderbrekingspunt op de methode dealloc instel, wordt het breekpunt nooit getroffen.

Wat denk jij?

3
Het probleem is opgelost door mijn project te converteren naar ARC: Bewerken> Refactor> Omzetten in doel-C ARC, voor meer informatie over ARC developer.apple.com/library/ios/#documentation/DeveloperTool‌ s/& hellip;
toegevoegd de auteur TS.xy, de bron

3 antwoord

Een paar observaties:

  1. person = nil geeft geen object vrij in niet-ARC-code. Het zal in ARC-code (tenminste als het sterk is).

  2. In ARC worden lokale objecten automatisch voor u vrijgegeven wanneer ze buiten het bereik vallen. In niet-ARC worden objecten die buiten het bereik vallen, niet voor je vrijgegeven (en als je elders geen verwijzingen naar die objecten hebt, krijg je een lek).

  3. Door een item aan een mutable array toe te voegen, wordt het aantal keren dat het item behouden blijft vergroot, dus zelfs als u een release opneemt in uw niet-ARC-code, wordt het object niet vrijgegeven totdat het aantal reserves tot nul is gedaald (Voltooid door niet alleen de persoonsobjecten vrij te geven nadat u ze aan de array hebt toegevoegd, maar ze ook uit de array te verwijderen.

Dus, aangezien dit niet-ARC-code is, kan het zoiets zijn als:

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

- (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
}
8
toegevoegd
Dit zou het geaccepteerde antwoord moeten zijn. Ik denk niet dat "verandering in ARC" deze vraag juist beantwoordt, omdat de vraag impliceert dat de persoon om de een of andere reden GEEN ARC gebruikt (wat opzettelijk had kunnen zijn) en dit antwoord is verklarend, en verklaart ook wat ARC zou zijn. anders doen.
toegevoegd de auteur Accatyyc, de bron

De juiste manier om objecten te bevrijden is doen

[employees release];

Als u deze instelt op nihil , wordt het geheugen niet vrijgegeven.

3
toegevoegd

By virtue of you being allowed to call [super dealloc], I can assume that you are not using Automatic Reference Counting. This means that you need to explicitly pair every alloc you write with a balancing release call. 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.

Het kan belangrijk zijn om op te merken dat ARC is gemaakt voor precies dit soort situaties; het is logisch voor onze hersenen, en nu kan het een realiteit zijn als je de nieuwste tools gebruikt.

2
toegevoegd
Bedankt ctrahey, ik heb mijn project omgezet naar ARC. Het werkt nu, en ik hoef [super dealloc] niet meer te bellen
toegevoegd de auteur TS.xy, de bron