当我使用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
答案 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;
}
这是因为copy
和alloc
都返回了保留的对象实例,您需要在完成它们时手动释放它们。您为已分配的对象正确执行了此操作,但未对副本执行此操作。
答案 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)
我没有答案,但我确实有一些一般性评论:
copyWithZone:
中,您应该使用allocWithZone:
(将相同的区域作为参数传递)来分配您要返回的对象。copyWithZone:
应该返回一个保留的对象。不要自动释放它。您不应该在init中使用属性。你的init应该看起来像:
-init
{
self = [super init];
if (self != nil)
{
lundi = [[Horaires alloc] init]; // assign the ivar directly
}
return self;
}
在您的copyWithZone:
HorairesCollection中,您有泄漏。它应该看起来像:
-(id)copyWithZone:(NSZone *)zone{
DefibHoraires *another = [[DefibHoraires allocWithZone: zone] init];
another.lundi = [[lundi copyWithZone: zone] autorelease];
return another;
}