Objective-C: Mocowanie zarządzanie pamięcią w metodzie

głosy
5

Ja prawie nie rozumiejąc proste zarządzanie liczenia odniesienia / pamięci w Objective-C, jednak mam trudny czas z następującego kodu. Jestem uwalniając mutableDict (skomentował w poniższym kodzie) i to jest przyczyną negatywnego zachowania w moim kodu. Jeśli pozwolę wyciek pamięci, to działa zgodnie z oczekiwaniami, ale z pewnością nie jest odpowiedź tutaj. ;-) Czy ktoś z was bardziej doświadczeni ludzie są na tyle uprzejmy, żeby wskazać mi w dobrym kierunku, jak mogę ponownie napisać żadnej z tej metody, aby lepiej obsługiwać moje zużycie pamięci? Głównie z tego jak mam zarządzający NSMutableDictionary * mutableDict, jako że jest wielkim winowajcą tutaj. Chciałbym, aby zrozumieć problem, a nie po prostu skopiować / wkleić kod - tak niektóre komentarze / feedback jest idealny. Dziękuje wszystkim.

- (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;
}
Utwórz 26/02/2009 o 23:32
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
5

Oto odpowiednik przepisanie kodu:

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

Zauważ, że nie tylko liczy na odniesienie theXMLDocument. To dlatego, że tablice i słowniki mieszkają poza zakres tej metody. arrayI dictionarymetody klasy utworzyć autoreleased instancje NSArrayi NSMutableDictionaryprzedmioty. Jeśli rozmówca nie jawnie je zachować, zostaną one automatycznie zwalniane na następnym go-round pętli zdarzeń aplikacji.

  • Ja również usunąć kod, który nigdy nie miał być wykonany. CXMLNode nameMetoda mówi, że zwraca ciąg znaków, więc ten test będzie zawsze prawdziwe.
  • Jeśli mutableDictjest nil, masz większe problemy. To lepiej, że zgłasza wyjątek niż cicho nie, więc zrobiłem precz z tego testu, zbyt.
  • Kiedyś również stosunkowo nową forskładnię wyliczenia, która znosi zmiennych licznika.
  • I przemianowany pewne zmienne i metody, aby być trochę bardziej Kakao-owski. Kakao różni się od większości języków w tym, że na ogół uważane za niewłaściwe użycie czasownika jak „stworzyć”, chyba że specjalnie chcesz, aby rozmówca odpowiedzialny za udostępnianie cokolwiek obiekt wrócisz.
  • Nie nic z robić theError. Należy też sprawdzić i zgłosić błąd, albo zdać się niljeśli nie zamierzamy to sprawdzić. Nie ma sensu w tworzeniu aplikacji zbudować obiekt o błędzie nie zamierzamy używać.

Mam nadzieję, że to pomoże Ci wskazał w dobrym kierunku.

Odpowiedział 27/02/2009 o 00:18
źródło użytkownik

głosy
1

Dobrze, uwalniając mutableDict naprawdę nie powinno być przyczyną problemów, ponieważ linia nad nim (dodawanie mutableDict do mutableArray) będzie go zatrzymać automatycznie. Chociaż nie jestem pewien, co dokładnie jest nie tak z kodem (nie określono, co „złe rzeczy” znaczy), istnieje kilka ogólnych rzeczy chciałbym zaproponować:

  1. Nie autorelease mutableArray razu. Niech to będzie regularne oświadczenie alloc / init i autorelease go, gdy go zwrócić ( „powrót [mutableArray autorelease];”).

  2. theXMLDocument przecieka, należy zwolnić, że przed powrotem. Ponadto, nie trzeba zachować ją jak ty. alloc / init wykonuje pracę uruchamiając obiekt zachować liczyć na 1, zachowując go ponownie tylko zapewnia ona przecieki zawsze. Pozbyć się zachować i zwolnić go przed powrotem i nie będzie przeciekać.

  3. Tylko wskazówka: upewnij się, że zachowują wartości zwracanej tej metody podczas używania go gdzie indziej - wynik został autoreleased jak nie gwarantuje się dookoła, kiedy trzeba, chyba że wyraźnie zachowują / uwolnienia go gdzieś.

W przeciwnym razie, ten kod powinien działać. Jeśli jeszcze nie, jeszcze jedno chciałbym spróbować to może robić [mutableArray addObject: [mutableDict skopiować]], aby upewnić się, że ci mutableDict powoduje żadnych problemów, gdy jest on zwolniony.

Odpowiedział 26/02/2009 o 23:49
źródło użytkownik

głosy
0

W Instrukcji programowania zarządzanie pamięcią w temacie Skrutacyjnej obiektów z Metod (przewinąć kawałek), istnieje kilka prostych przykładów, w jaki sposób powrócić obiekty z metody z prawidłowym managment pamięci.

Odpowiedział 08/09/2010 o 22:48
źródło użytkownik

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