Objective C 内存泄漏

发布于 2024-09-11 21:38:36 字数 8217 浏览 3 评论 0原文

这里有两个方法返回我的自定义四属性对象的字典。他们创建字符串、浮点数和 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;
}

Here are two methods that return a dictionary of my custom four-propery objects. They make arrays of strings, floats and BOOLs to put in the Chemical objects, then build a dictionary from the arrays. I'm new enough to the whole memory management game that I'm not always sure when I own something and when to release it. I'm making all kinds of strings on the fly.

Here's the thing: The static analyzer sees no problem with the first method, - (id)generateChlorineDictionary but says there's a leak in the second one, - (id)generateCYADictionary. It says it starts at the NSMutableArray *cyaGranulesArray... and then goes to NSDictionary *cyaDictionary... and finally to the return cyaDictionary statement.

Here are the two methods; sorry they're so long!


EDIT: Changed name from generateChlorineDictionary to newChlorineDictionary
Removed a release that happened after the return

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

EDIT: Changed name from generateCYADictionary to newCYADictionary
Removed a release that happened after the return

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦回梦里 2024-09-18 21:38:36

替换

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”开头方法名称......

编辑(重要)
您应该只使用我的建议之一。

  • return 行中使用 autorelease
  • 使用 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

Replace the

return cyaDictionary;
[cyaDictionary release];

With

return [cyaDictionary autorelease];

Or, you might replace the

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

With

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

Instead of adding the autorelease.

In your original implementation the [cyaDictionary release]; is never executed (because it is after return).

You can use this dictionary outside this method and you shouldn't release it there.

You might want also return a retained object (without the autorelease) and release it outside the method. In this case you should start the method name with "new" or "alloc"...

EDIT (Important):
You should use only one of my suggestions.

  • Use the autorelease in the return line
  • Use the dictionaryWith...
  • Add the "new" or "alloc" prefix in the method name and release the returned object outside this method.

If you replace the alloc init with dictionaryWith... then you get an autoreleased object. And then, if you release it in the outer method then you have a serious problem (the object will try to release itself after the current runloop of the thread and it may crash the app because the object will already be released by you).

EDIT (due to one of the comments)
If you want to create a property that will return a dictionary:

// 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文