Cíl-C: Upevňovací správa paměti v metodě

hlasů
5

Už jsem skoro tam porozumění jednoduchou správu počítání referencí / paměti v Objective-C, ale mám těžký čas s následujícím kódem. Jsem uvolnění mutableDict (komentoval v kódu níže) a to způsobuje nežádoucí chování v mém kódu. Kdybych nechal únik paměti, to funguje, jak se očekávalo, ale to zjevně není odpověď zde. ;-) Byl by tak laskav a místo mě tím správným směrem, jak, jak mohu přepsat některou z této metody, aby lépe zvládnout mé nároky na paměť se někdo z vás zkušenější lidi? Hlavně s tím, jak Vedu NSMutableDictionary * mutableDict, protože to je velký viníkem. Chtěl bych porozumět problému, a ne jen kopírovat / vložit kód - takže některé poznámky / zpětná vazba je ideální. Děkuji všem.

- (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;
}
Položena 26/02/2009 v 23:32
zdroj uživatelem
V jiných jazycích...                            


3 odpovědí

hlasů
5

Zde je ekvivalent přepsání kódu:

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

Všiml jsem si jen dělal odkaz na počítání theXMLDocument. To proto, že pole a slovníky žít nad rámec tohoto způsobu. arrayA dictionarymetody třídy vytvořit autoreleased instance NSArraya NSMutableDictionaryobjektů. Pokud volající není explicitně zachovat, budou automaticky uvolní na další kolotoč smyčky událostí aplikace.

  • Také jsem odstranil kód, který se nikdy nebude vykonán. CXMLNode nameMetoda říká, že vrátí řetězec, takže test bude vždy pravda.
  • Pokud mutableDictje nilmáte větší problémy. Je lepší, že to způsobí výjimku, než tiše selhat a tak jsem se zbavil tohoto testu, taky.
  • Také jsem použil relativně nový forvýčtu syntaxi, která dělá pryč s vašimi pult proměnných.
  • přejmenoval jsem nějaké proměnné a metody, aby bylo trochu víc Cocoa-ish. Kakao je odlišný od většiny jazyků v tom, že je obecně považována za nesprávné používat sloveso jako „vytvořit“ pokud si výslovně chcete, aby volající odpovědný za uvolnění čehokoliv objekt vrátíte.
  • Neudělal jsi nic s theError. Měli byste buď zkontrolovat a nahlásit chybu, anebo předat nil, pokud nebudeme ho kontrolovat. Tam je při vytváření app stavět objekt chyby vy nebudete používat žádný smysl.

Doufám, že to pomůže vám ukázal správným směrem.

Odpovězeno 27/02/2009 v 00:18
zdroj uživatelem

hlasů
1

No, uvolňující mutableDict opravdu neměl způsobovat žádné problémy, protože řádek nad ním (přidávání mutableDict do mutableArray) se automaticky udržet. I když si nejsem jistý, co přesně je špatně s kódem (jste neupřesnila, co „špatné věci“ se rozumí), je tu několik obecných věcí Navrhoval bych:

  1. Nenechte autorelease mutableArray hned. Nech to být pravidelná prohlášení alloc / init a autorelease ji, když ji vrátit ( "vrátit [mutableArray autorelease];").

  2. theXMLDocument uniká, je nutné uvolnit, že před návratem. Také nemusíte udržet to, jako byste se. alloc / init dělá svou práci tím, že začíná objekt udržet počet 1, jej zachovat opět jen zajišťuje, že uniká navždy. Zbavte se udržet a uvolněte jej, než se vrátí a nebude unikat.

  3. Jen tip: být jisti, že při jeho použití na jiném místě zachovat návratovou hodnotu této metody - výsledek byl autoreleased protože není zaručeno, že bude u toho, když ji budete potřebovat, pokud si výslovně zachovat / uvolnit ho někde.

V opačném případě tento kód by měl fungovat. Pokud to stále není, ještě jedna věc, kterou bych zkusit se snad dělá [mutableArray AddObject: [mutableDict copy]], aby mutableDict vám způsobí žádné problémy, když je propuštěn.

Odpovězeno 26/02/2009 v 23:49
zdroj uživatelem

hlasů
0

V paměti řídícího Programming Guide v tématu Vracíte objekty z metod (nalistujte trochu), existuje několik jednoduchých příkladů, jak se vrátit objekty z metody se správným správa paměti.

Odpovězeno 08/09/2010 v 22:48
zdroj uživatelem

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