Obiectiv-C: FIXARE gestionare a memoriei într-o metodă

voturi
5

Sunt aproape simplă înțelegere de management de numărare de referință / de memorie în Objective-C, cu toate acestea am o perioadă dificilă, cu următorul cod. Sunt eliberarea mutableDict (a comentat în codul de mai jos) și cauzează un comportament dăunător în codul meu. Dacă am lăsat scurgere de memorie, funcționează cum era de așteptat, dar asta nu e clar răspunsul aici. ;-) Vrei oricare dintre voi oameni mai experimentați să fie un fel de ajuns pentru a-mi punct în direcția cea bună ca și cum pot re-scrie oricare dintre aceste metode pentru a gestiona mai bine amprenta de memorie? În principal, cu modul în care Gestionez NSMutableDictionary * mutableDict, ca este mare vinovat aici. Aș vrea să înțeleg problema, și nu doar copy / paste codul - astfel încât unele comentarii / feedback-ul este ideal. Multumesc tuturor.

- (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;
}
Întrebat 26/02/2009 la 23:32
sursa de către utilizator
În alte limbi...                            


3 răspunsuri

voturi
5

Iată o rescriere echivalentă a codului:

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

Observați am făcut doar de referință de numărare pe theXMLDocument. Asta pentru că matricele și dicționare trăiesc dincolo de sfera de aplicare a acestei metode. arrayȘi dictionarymetodele clasei crea instanțe autoreleased de NSArrayși NSMutableDictionaryobiecte. În cazul în care apelantul nu le reține în mod explicit, acestea vor fi eliberate în mod automat pe următoarea rundă de du - te-bucla eveniment aplicației.

  • Am eliminat , de asemenea , un cod care nu a fost niciodată de gând să fie executat. CXMLNode nameMetoda spune că returnează un șir de caractere, astfel încât testul va fi întotdeauna adevărat.
  • Dacă mutableDicteste nil, ai probleme mai mari. E mai bine că aruncă o excepție decât eșuează în tăcere, așa că am făcut departe cu acest test, de asemenea.
  • Am folosit , de asemenea , relativ noua forsintaxă enumerare, care nu departe cu variabilele contra.
  • Am redenumit unele variabile și metoda de a fi un pic mai mult de cacao-ish. Cacao este diferit de cele mai multe limbi în care este considerat în general incorect de a folosi un verb ca „a crea“ cu excepția cazului în care doriți în mod specific pentru a face apelantului responsabil pentru eliberarea orice obiect te vei întoarce.
  • N - ai făcut nimic cu theError. Ar trebui să fie să verificați și să raporteze eroarea, sau treci în nilcazul în care nu o să - l verifice. Nu există nici un sens în a face app construi un obiect de eroare pe care nu vei folosi.

Sper că acest lucru ajută să vă arătat în direcția cea bună.

Publicat 27/02/2009 la 00:18
sursa de către utilizator

voturi
1

Ei bine, mutableDict eliberarea într-adevăr nu ar trebui să fie a cauza probleme, deoarece linia de mai sus (adăugarea de mutableDict la mutableArray) se va reține în mod automat. În timp ce eu nu sunt sigur exact ceea ce se întâmplă în neregulă cu codul dvs. (nu a precizat ce „lucruri rele“ înseamnă), există câteva lucruri generale, aș sugera:

  1. Nu AutoreleasePool mutableArray imediat. Să fie o declarație regulat aloc / de inițializare și AutoreleasePool-l atunci când îl întoarce ( „return [mutableArray AutoreleasePool];“).

  2. theXMLDocument se scurge, asigurați-vă că pentru a elibera înainte de a reveni. De asemenea, nu trebuie să-l păstreze ca tine sunt. aloc / init face treaba pornind obiectului reține numărul de la 1, păstrând-o din nou doar asigură-l scurgeri de informații pentru totdeauna. Scapă de reține și eliberați-l înainte de a reveni si nu se va scurge.

  3. Doar un sfat: asigurați-vă că vă păstrați valoarea returnată a acestei metode atunci când utilizați în altă parte - rezultatul a fost autoreleased ca nu este garantată a fi în jurul valorii de când ai nevoie de ea decât dacă reține în mod explicit / eliberați-l undeva.

În caz contrar, acest cod ar trebui să funcționeze. Dacă tot nu, un lucru aș încerca este , poate face [mutableArray addObject: [mutableDict copie]] pentru a se asigura că mutableDict vă cauzează probleme atunci când este eliberat.

Publicat 26/02/2009 la 23:49
sursa de către utilizator

voturi
0

În Ghidul de programare Managementul memoriei sub tema recurenți obiecte din metodele (derulați în jos un pic), există câteva exemple simple despre cum să se întoarcă de obiecte dintr - o metodă cu managmentul de memorie corectă.

Publicat 08/09/2010 la 22:48
sursa de către utilizator

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