在alloc上使用objective-c进行内存泄漏

时间:2011-01-10 09:02:42

标签: objective-c

当我使用Instruments查找内存泄漏时,会在

上检测到泄漏
Horaires *jour;     
jour= [[Horaires alloc] init]; // memory leak reported here by Instruments
self.lundi = jour;
[jour release];

我不知道为什么会发生泄漏。

有人可以帮助我吗?这是代码。

// HorairesCollection.h
#import <Foundation/Foundation.h>
#import "Horaires.h"

@interface HorairesCollection : NSObject < NSCopying > {
    Horaires *lundi;
}

@property (nonatomic, retain) Horaires *lundi;
-init;
-(void)dealloc;
@end


// HorairesCollection.m
#import "HorairesCollection.h"

@implementation HorairesCollection

@synthesize lundi;

-(id)copyWithZone:(NSZone *)zone{
    HorairesCollection *another = [[HorairesCollection alloc] init];
    another.lundi = [lundi copyWithZone: zone];
    [another autorelease];
    return another;
}

-init{
    self = [super init];
    Horaires *jour;     
    jour= [[Horaires alloc] init]; // memory leak reported here by Instruments
    self.lundi = jour;
    [jour release];
    return self;
}

- (void)dealloc {
    [lundi release];
    [super dealloc];
}

@end


// Horaires.h
#import <Foundation/Foundation.h>

@interface Horaires : NSObject <NSCopying>{
    BOOL ferme;
    BOOL h24;
    NSString *h1;
}

@property (nonatomic, assign) BOOL ferme;
@property (nonatomic, assign) BOOL h24;
@property (nonatomic, retain) NSString *h1;

-init;
-(id)copyWithZone:(NSZone *)zone;
-(void)dealloc;

@end


// Horaires.m
#import "Horaires.h"
@implementation Horaires

-(BOOL) ferme {
    return ferme;
}

-(void)setFerme:(BOOL)bFerme{
    ferme = bFerme;
    if (ferme) {
        self.h1 = @"";
        self.h24 = NO;
    }
}

-(BOOL) h24 {
    return h24;
}

-(void)setH24:(BOOL)bH24{
    h24 = bH24;
    if (h24) {
        self.h1 = @"";
        self.ferme = NO;
    }
}

-(NSString *) h1 {
    return h1;
}

-(void)setH1:(NSString *)horaire{
    [horaire retain];
    [h1 release];
    h1 = horaire;
    if (![h1 isEqualToString:@""]) {
        self.h24 = NO;
        self.ferme = NO;
    }
}

-(id)copyWithZone:(NSZone *)zone{
    Horaires *another = [[Horaires alloc] init];
    another.ferme = self.ferme;
    another.h24 = self.h24;
    another.h1 = self.h1;
    [another autorelease];
    return another;
}

-init{
    self = [super init];
    return self;
}

-(void)dealloc {
    [h1 release];
    [super dealloc];
}

@end

3 个答案:

答案 0 :(得分:2)

你已经将你的属性设置为retain并且你分配并释放变量,所以从我所看到的代码是可以的,而且Instruments已经给你一个错误的警告。

我认为你的copyWithZone:可能会有泄密。 [lundi copyWithZone:]会保留lundi的副本,但您永远不会发布它。所以你需要一个额外的版本,如下所示:

-(id)copyWithZone:(NSZone *)zone{
    DefibHoraires *another = [[DefibHoraires alloc] init];
    Horaires* makeCopy = [lundi copyWithZone: zone];
    another.lundi = makeCopy;
    [makeCopy release];
    return another;
}

这是因为copyalloc都返回了保留的对象实例,您需要在完成它们时手动释放它们。您为已分配的对象正确执行了此操作,但未对副本执行此操作。

答案 1 :(得分:0)

init方法看起来不错,尽管它应该被实现(和键入)为

-(id)init
{
    if (self = [super init])
    {
        ...
    }
    return self;
}

或类似的模式。

你的copyWithZone实现是错误的,他们需要返回一个保留的对象,所以不要自动释放返回的值。但是您需要发布lundi的副本,因为您正在使用保留设置器。

-(id)copyWithZone:(NSZone *)zone{
    DefibHoraires *another = [[DefibHoraires alloc] init];
    Horaires *lundiCopy = [lundi copyWithZone:zone];    
    another.lundi = lundiCopy;
    [lundiCopy release];
    return another;
}

我不知道为什么你在这里返回DefibHoraires的实例,不应该是HorairesCollection吗?

可能错误的copyWithZone:方法负责报告泄漏(无论如何都是泄漏)。

还有一点需要注意:使用(copy) NSString属性代替(retain)代替NSMutableString移除{{1}}时的副作用是一个很好的防御规则。

答案 2 :(得分:0)

我没有答案,但我确实有一些一般性评论:

  1. copyWithZone:中,您应该使用allocWithZone:(将相同的区域作为参数传递)来分配您要返回的对象。
  2. copyWithZone:应该返回一个保留的对象。不要自动释放它。
  3. 您不应该在init中使用属性。你的init应该看起来像:

    -init
    {
        self = [super init];
        if (self != nil)
        {
            lundi = [[Horaires alloc] init]; // assign the ivar directly
        }
        return self;
    }
    
  4. 在您的copyWithZone: HorairesCollection中,您有泄漏。它应该看起来像:

    -(id)copyWithZone:(NSZone *)zone{
        DefibHoraires *another = [[DefibHoraires allocWithZone: zone] init];
        another.lundi = [[lundi copyWithZone: zone] autorelease];
        return another;
    }