When I use Instruments to find memory leaks, a leak is detected on
Horaires *jour;
jour= [[Horaires alloc] init]; // memory leak reported here by Instruments
self.lundi = jour;
[jour release];
and I don't know why there is a leak at this point.
Does anyone can help me? Here's the code.
// 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
You've set your property to retain and you alloc and release the variable, so from what I can see the code is okay and Instruments has given you a false warning.
I think your copyWithZone:
might have a leak, though. [lundi copyWithZone:]
will retain a copy of lundi
but you never release it. So you need an extra release, something like this:
-(id)copyWithZone:(NSZone *)zone{
DefibHoraires *another = [[DefibHoraires alloc] init];
Horaires* makeCopy = [lundi copyWithZone: zone];
another.lundi = makeCopy;
[makeCopy release];
return another;
}
This is because copy
and alloc
both return retained object instances and you need to manually release them when you're finished with them. You did that correctly for your alloc'd objects but not the copy.
That init
method looks ok, although it should be implemented (and typed) as
-(id)init
{
if (self = [super init])
{
...
}
return self;
}
or a similar pattern.
Your copyWithZone implementations are wrong, they need to return a retained object, so do not autorelease the returned value. But you need to release your copy of lundi
, because you are using the retaining setter.
-(id)copyWithZone:(NSZone *)zone{
DefibHoraires *another = [[DefibHoraires alloc] init];
Horaires *lundiCopy = [lundi copyWithZone:zone];
another.lundi = lundiCopy;
[lundiCopy release];
return another;
}
I don't know why you return an instance of DefibHoraires
here, shouldn't it be a HorairesCollection
?
Maybe the wrong copyWithZone: method is responsible for the reported leak (it's a leak anyway).
One further note: It's a good defensive rule to use (copy)
for NSString
properties instead of (retain)
to remove side effects when passing NSMutableString
instead.
I don't have an answer but I do have some general comments:
- In
copyWithZone:
you should useallocWithZone:
(passing the same zone as a parameter) to allocate the object you are going to return. copyWithZone:
should return a retained object. Don't autorelease it.You are not supposed to use properties in init. Your init should look something like:
-init { self = [super init]; if (self != nil) { lundi = [[Horaires alloc] init]; // assign the ivar directly } return self; }
In your
copyWithZone:
for HorairesCollection you have a leak. It should look like:-(id)copyWithZone:(NSZone *)zone{ DefibHoraires *another = [[DefibHoraires allocWithZone: zone] init]; another.lundi = [[lundi copyWithZone: zone] autorelease]; return another; }
精彩评论