Objective-C: Bevestiging geheugenbeheer bij een werkwijze

stemmen
5

Ik ben er bijna begrijpen eenvoudige verwijzing tellen / geheugenbeheer in Objective-C, maar ik heb een moeilijke tijd met de volgende code. Ik ben het vrijgeven van mutableDict (commentaar in de onderstaande code) en het veroorzaakt schadelijk gedrag in mijn code. Als ik laat de geheugenlek, het werkt zoals verwacht, maar dat is duidelijk niet het antwoord hier. ;-) Zou iemand van jullie meer ervaren mensen zijn vriendelijk genoeg om me in de juiste richting als hoe ik kan herschrijven elk van deze methode om beter om met mijn memory footprint? Vooral met de manier waarop ik het beheren van NSMutableDictionary * mutableDict, want dat is de grote boosdoener hier. Ik wil graag het probleem te begrijpen, en niet alleen copy / paste-code - dus enkele opmerkingen / feedback is ideaal. Bedankt allemaal.

- (NSArray *)createArrayWithDictionaries:(NSString *)xmlDocument 
                               withXPath:(NSString *)XPathStr {

    NSError *theError = nil;
    NSMutableArray *mutableArray = [[[NSMutableArray alloc] init] autorelease];
    //NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
    CXMLDocument *theXMLDocument = [[[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError] retain]; 
    NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];
    int i, j, cnt = [nodes count];
    for(i=0; i < cnt; i++) {
        CXMLElement *xmlElement = [nodes objectAtIndex:i];
        if(nil != xmlElement) {
            NSArray *attributes = [NSArray array];
            attributes = [xmlElement attributes];
            int attrCnt = [attributes count];
            NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
            for(j = 0; j < attrCnt; j++) {
                if([[[attributes objectAtIndex:j] name] isKindOfClass:[NSString class]]) 
                    [mutableDict setValue:[[attributes objectAtIndex:j] stringValue] forKey:[[attributes objectAtIndex:j] name]];
                else 
                    continue;
            }
            if(nil != mutableDict) {
                [mutableArray addObject:mutableDict];
            }
            [mutableDict release];  // This is causing bad things to happen.
        }
    }

    return (NSArray *)mutableArray;
}
De vraag is gesteld op 26/02/2009 om 23:32
bron van user
In andere talen...                            


3 antwoorden

stemmen
5

Hier is een equivalent herschrijven van je code:

- (NSArray *)attributeDictionaries:(NSString *)xmlDocument withXPath:(NSString *)XPathStr {
    NSError *theError = nil;
    NSMutableArray *dictionaries = [NSMutableArray array];
    CXMLDocument *theXMLDocument = [[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError]; 
    NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];

    for (CXMLElement *xmlElement in nodes) {
        NSArray *attributes = [xmlElement attributes];
        NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
        for (CXMLNode *attribute in attributes) {
            [attributeDictionary setObject:[attribute stringValue] forKey:[attribute name]];
        }

        [dictionaries addObject:attributeDictionary];
    }

    [theXMLDocument release];
    return attributeDictionaries;
}

Let op, ik heb enige verwijzing rekenen op theXMLDocument. Dat komt omdat de arrays en woordenboeken leven buiten het bestek van deze methode. De arrayen dictionarymethoden van de klasse te creëren autoreleased gevallen van NSArrayen NSMutableDictionaryobjecten. Als de beller ze niet expliciet te behouden, zullen ze automatisch worden vrijgegeven op de volgende go-round van het evenement lus van de toepassing.

  • Ik verwijderde ook code die nooit zou worden geëxecuteerd. De CXMLNode namemethode zegt dat het een tekenreeks, zodat test zal altijd waar zijn.
  • Als mutableDictis nil, heb je grotere problemen. Het is beter dat het een uitzondering is dan stil mislukken, dus deed ik weg met die test, ook.
  • Ik heb ook de relatief nieuwe foropsomming syntax, die weg doet met uw teller variabelen.
  • Ik heb de namen enkele variabelen en de methode om een ​​beetje meer van de cacao-achtig. Cacao is anders dan de meeste talen in dat het over het algemeen onjuist is beschouwd als een werkwoord als "scheppen", tenzij u specifiek wilt de beller die verantwoordelijk is voor het vrijgeven van wat object dat u terug te gebruiken.
  • Je hebt niets aan doen theError. Je moet ook controleren en rapporteren van de fout, of anders pas in nilals je niet van plan om het te controleren. Er is geen zin in het maken van de app te bouwen een fout object dat je niet gaat gebruiken.

Ik hoop dat dit helpt krijg je wees in de goede richting.

antwoordde op 27/02/2009 om 00:18
bron van user

stemmen
1

Nou, het vrijgeven van mutableDict echt mag niet worden veroorzaakt geen problemen omdat de regel erboven (het toevoegen van mutableDict naar mutableArray) zal het automatisch behouden. Hoewel ik weet niet zeker wat er precies fout gaat met uw code (u heeft niet aangegeven wat de "slechte dingen" betekent), er zijn een paar algemene dingen die ik zou willen voorstellen:

  1. Niet autorelease mutableArray meteen. Laat het een regelmatige alloc / init statement en autorelease het wanneer je het terug ( "return [mutableArray autorelease];").

  2. theXMLDocument lekt, moet u vrij te geven dat alvorens terug te keren. Ook hoeft u niet nodig om het te behouden als je bent. alloc / init doet het werk door het starten van het object te behouden telling per 1, met behoud van het weer gewoon zorgt ervoor dat het voor altijd lekt. Zich te ontdoen van de te behouden en laat hem los alvorens terug te keren en het zal niet lekken.

  3. Gewoon een tip: zorg ervoor dat u de return waarde van deze methode te behouden wanneer u het ergens anders - het resultaat is autoreleased als er geen garantie dat rond wanneer je het nodig hebt, tenzij je expliciet behouden / loslaten ergens.

Anders, deze code moet werken. Als het nog steeds niet het geval is, is een ander ding dat ik zou proberen misschien doen [mutableArray addObject: [mutableDict kopiëren]] om ervoor te zorgen dat mutableDict ervoor zorgt dat je geen problemen wanneer het wordt losgelaten.

antwoordde op 26/02/2009 om 23:49
bron van user

stemmen
0

In Memory Management Programming Guide onder het thema Terugkerend Objecten uit Methods (scroll naar beneden een beetje), er zijn een paar eenvoudige voorbeelden over hoe om objecten terug te keren van een methode met de juiste geheugenbeheer.

antwoordde op 08/09/2010 om 22:48
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more