Цель c утечкой памяти - PullRequest
       31

Цель c утечкой памяти

0 голосов
/ 28 июля 2010

Вот два метода, которые возвращают словарь моих пользовательских объектов. Они создают массивы строк, чисел с плавающей запятой и BOOL для размещения объектов Chemical, а затем строят словарь из массивов. Я достаточно новичок во всей игре по управлению памятью, поэтому не всегда уверен, когда у меня есть что-то, а когда - выпустить. Я делаю все виды струн на лету.

Вот в чем дело: статический анализатор не видит проблем с первым методом, - (id)generateChlorineDictionary, но говорит, что во втором, - (id)generateCYADictionary, есть утечка. Он говорит, что начинается с NSMutableArray *cyaGranulesArray..., затем переходит к NSDictionary *cyaDictionary... и, наконец, к оператору return cyaDictionary.

Вот два метода; извините, они так долго!


РЕДАКТИРОВАТЬ: изменено имя с generateChlorineDictionary на newChlorineDictionary
Удален релиз, произошедший после возврата

- (id)newChlorineDictionary {
// Sets up the array for the Bleach key
    NSMutableArray *bleachArray = [[NSMutableArray alloc] init]; 
    NSArray *bleachConcentrationArray = [[NSArray alloc] initWithObjects:@"6%", @"10%", @"12%", nil];
    float bleachConstantArray[] = {0.0021400, 0.0012840, 0.0010700};
    for (int i=0; i<3; i++) {
        Chemical *bleachChemical = [[Chemical alloc] initWithChemical:@"Bleach" 
                                                andConcentration:[bleachConcentrationArray objectAtIndex:i] 
                                                     andConstant:bleachConstantArray[i] 
                                                     andIsLiquid:YES];
        [bleachArray addObject:bleachChemical];
        NSLog(@"bleachChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", bleachChemical.chemName, bleachChemical.chemConcentration, bleachChemical.chemConstant, bleachChemical.chemIsLiquid);
        [bleachChemical release];
    }
    bleachConcentrationArray = nil;
// Sets up the array for the Trichlor key   
    NSMutableArray *trichlorArray = [[NSMutableArray alloc] init];
    Chemical *trichlorChemical = [[Chemical alloc] initWithChemical:@"Trichlor" 
                                            andConcentration:@"90%" 
                                                 andConstant:0.0001480
                                                 andIsLiquid:NO];
    [trichlorArray addObject:trichlorChemical];
    NSLog(@"trichlorChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", trichlorChemical.chemName, trichlorChemical.chemConcentration, trichlorChemical.chemConstant, trichlorChemical.chemIsLiquid);
    [trichlorChemical release];
// Sets up the array for the Dichlor key
    NSMutableArray *dichlorArray = [[NSMutableArray alloc] init]; 
    NSArray *dichlorConcentrationArray = [[NSArray alloc] initWithObjects:@"56%", @"62%", nil];
    float dichlorConstantArray[] = {0.0002400, 0.0002168};
    for (int i=0; i<2; i++) {
        Chemical *dichlorChemical = [[Chemical alloc] initWithChemical:@"Dichlor" 
                                                andConcentration:[dichlorConcentrationArray objectAtIndex:i] 
                                                     andConstant:dichlorConstantArray[i] 
                                                     andIsLiquid:NO];
        [dichlorArray addObject:dichlorChemical];
        NSLog(@"dichlorChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", dichlorChemical.chemName, dichlorChemical.chemConcentration, dichlorChemical.chemConstant, dichlorChemical.chemIsLiquid);
        [dichlorChemical release];
    }
    dichlorConcentrationArray = nil;
// Sets up the array for the Cal Hypo key
    NSMutableArray *calHypoArray = [[NSMutableArray alloc] init]; 
    NSArray *calHypoConcentrationArray = [[NSArray alloc] initWithObjects:@"48%", @"53%", @"65", @"73", nil];
    float calHypoConstantArray[] = {0.0002817, 0.0002551, 0.0002080, 0.0001852};
    for (int i=0; i<2; i++) {
        Chemical *calHypoChemical = [[Chemical alloc] initWithChemical:@"Cal Hypo" 
                                                andConcentration:[calHypoConcentrationArray objectAtIndex:i] 
                                                     andConstant:calHypoConstantArray[i] 
                                                     andIsLiquid:NO];
        [calHypoArray addObject:calHypoChemical];
        NSLog(@"calHypoChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", calHypoChemical.chemName, calHypoChemical.chemConcentration, calHypoChemical.chemConstant, calHypoChemical.chemIsLiquid);
        [calHypoChemical release];
    }
    calHypoConcentrationArray = nil;
// Sets up the array for the Li Hypo key    
    NSMutableArray *liHypoArray = [[NSMutableArray alloc] init];
    Chemical *liHypoChemical = [[Chemical alloc] initWithChemical:@"Li Hypo" 
                                            andConcentration:@"90%" 
                                                 andConstant:0.0003800
                                                 andIsLiquid:NO];
    [liHypoArray addObject:liHypoChemical];
    NSLog(@"liHypoChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", liHypoChemical.chemName, liHypoChemical.chemConcentration, liHypoChemical.chemConstant, liHypoChemical.chemIsLiquid);
    [liHypoChemical release];
// The array of keys for the chlorine chemicals
    NSArray *chlorineKeys = [[NSArray alloc] initWithObjects:@"Bleach", @"Trichlor", @"Dichlor", @"Cal Hypo", @"Li Hypo", nil];
// The array of values for the chlorine chemicals
    NSArray *chlorineValues = [[NSArray alloc] initWithObjects:bleachArray, trichlorArray, dichlorArray, calHypoArray, liHypoArray, nil];
    [bleachArray release];
    [trichlorArray release];
    [dichlorArray release];
    [calHypoArray release];
    [liHypoArray release];
// The dictionary to hold the arrays of chlorine chemical objects
    NSDictionary *chlorineDictionary = [[NSDictionary alloc] initWithObjects:chlorineValues forKeys:chlorineKeys];
    [chlorineValues release];
    [chlorineKeys release];
    return chlorineDictionary;
}

РЕДАКТИРОВАТЬ: изменено имя с generateCYADictionary на newCYADictionary
Удален релиз, произошедший после возврата

- (id)newCYADictionary {
    // Sets up the array for the CYA Granules key   
    NSMutableArray *cyaGranulesArray = [[NSMutableArray alloc] init];
    Chemical *cyaGranulesChemical = [[Chemical alloc] initWithChemical:@"CYA Granules" 
                                                   andConcentration:@"" 
                                                        andConstant:0.0001330
                                                        andIsLiquid:NO];
    [cyaGranulesArray addObject:cyaGranulesChemical];
    NSLog(@"cyaGranulesChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", cyaGranulesChemical.chemName, cyaGranulesChemical.chemConcentration, cyaGranulesChemical.chemConstant, cyaGranulesChemical.chemIsLiquid);
    [cyaGranulesChemical release];
    // Sets up the array for the Liquid Stabilizer key  
    NSMutableArray *liquidStabilizerArray = [[NSMutableArray alloc] init];
    Chemical *liquidStabilizerChemical = [[Chemical alloc] initWithChemical:@"Liquid Stabilizer" 
                                                 andConcentration:@"" 
                                                      andConstant:0.0003460
                                                      andIsLiquid:YES];
    [liquidStabilizerArray addObject:liquidStabilizerChemical];
    NSLog(@"liquidStabilizerChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", liquidStabilizerChemical.chemName, liquidStabilizerChemical.chemConcentration, liquidStabilizerChemical.chemConstant, liquidStabilizerChemical.chemIsLiquid);
    [liquidStabilizerChemical release];
    // The array of keys for the CYA chemicals
    NSArray *cyaKeys = [[NSArray alloc] initWithObjects:@"CYA Granules", @"Liquid Stabilizer", nil];
    // The array of values for the CYA chemicals
    NSArray *cyaValues = [[NSArray alloc] initWithObjects:cyaGranulesArray, liquidStabilizerArray, nil];
    [cyaGranulesArray release];
    [liquidStabilizerArray release];
    // The dictionary to hold the arrays of CYA chemical objects
    NSDictionary *cyaDictionary = [[NSDictionary alloc] initWithObjects:cyaValues forKeys:cyaKeys]; 
    [cyaKeys release];
    [cyaValues release];
    return cyaDictionary;
}

1 Ответ

3 голосов
/ 28 июля 2010

Заменить

return cyaDictionary;
[cyaDictionary release];

С

return [cyaDictionary autorelease];



Или вы можете заменить

NSDictionary *chlorineDictionary = [[NSDictionary alloc] initWithObjects:chlorineValues forKeys:chlorineKeys];

С

NSDictionary *chlorineDictionary = [NSDictionary dictionaryWithObjects:chlorineValues forKeys:chlorineKeys];

Вместо добавления autorelease.

В исходной реализации [cyaDictionary release]; никогда не выполняется (потому что это после return).

Вы можете использовать этот словарь вне этого метода, и вы не должны выпускать его там.

Вы можете также вернуть сохраненный объект (без autorelease) и освободить его вне метода. В этом случае вы должны начать имя метода с «new» или «alloc» ...

РЕДАКТИРОВАТЬ (Важно) :
Вы должны использовать только одно из моих предложений.

  • Используйте autorelease в строке return
  • Используйте dictionaryWith...
  • Добавьте префикс «new» или «alloc» в имя метода и освободите возвращенный объект вне этого метода.

Если вы замените alloc init на dictionaryWith..., тогда вы получите объект с автоматическим освобождением. И затем, если вы освободите его во внешнем методе, у вас возникнет серьезная проблема (объект попытается освободить себя после текущего цикла выполнения потока, и это может привести к сбою приложения, поскольку объект уже будет освобожден вами).

РЕДАКТИРОВАТЬ (из-за одного из комментариев)
Если вы хотите создать свойство, которое будет возвращать словарь:

// MyClass.h file
@interface MyClass : NSObject {

    ..

    NSDictionary *_dict1;

    ..

}

@property (nonatomic, retain) NSDictionary *dict1;

..

@end

// MyClass.m file

@implementation MyClass

@synthesize dict1 = _dict1;

..

- (NSDictionary *)dict1 {
    if (_dict1 == nil) {
        NSDictionary *dict1Temp = [NSDictionary new];

        // Your implementation goes here...

        self.dict1 = dict1Temp;
        [dict1Temp release];
    }
}

..

- (void)dealloc {
    [_dict1 release];
    [suoer dealloc];
}

@end
...