Утечка памяти при использовании target-c на alloc - PullRequest
0 голосов
/ 10 января 2011

Когда я использую Инструменты для обнаружения утечек памяти, утечка обнаружена на

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 ]

2 голосов
/ 10 января 2011

Вы установили свойство для сохранения и распределяете и отпускаете переменную, так что, насколько я вижу, код в порядке, и 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;
}

Это связано с тем, что copy и alloc возвращают экземпляры сохраненных объектов, и вам нужно вручную освобождать их, когда вы закончите с ними. Вы сделали это правильно для своих выделенных объектов, но не для копии.

0 голосов
/ 10 января 2011

У меня нет ответа, но у меня есть некоторые общие комментарии:

  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;
    }
    
0 голосов
/ 10 января 2011

Этот 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 вместо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...