iPhone中的未知内存泄漏

时间:2011-04-03 20:22:10

标签: iphone string memory-leaks autorelease

我目前正在为iPhone构建一个应用程序,无法弄清楚为什么我会在Leaks Instrument工具中出现内存泄漏。

这是代码,我已经在两个地方添加了评论。

NSString *pathname = [[NSBundle mainBundle]  pathForResource:self.toUseFile ofType:@"txt" inDirectory:@"/"];
    //Line below causes a leak
    self.rawCrayons = [[NSString stringWithContentsOfFile:pathname encoding:NSUTF8StringEncoding error:nil] componentsSeparatedByString:@"\n"];

    self.sectionArray = [NSMutableArray array];
    for (int i = 0; i < 26; i++) [self.sectionArray addObject:[NSMutableArray array]];


    for(int i=0; i<self.rawCrayons.count; i++)
    {
        self.string = [self.rawCrayons objectAtIndex:i];
        NSUInteger firstLetter = [ALPHA rangeOfString:[string substringToIndex:1]].location;
        if (firstLetter != NSNotFound)
        {
            NSInteger audio = AUDIONUM(self.string);
            NSInteger pictures = PICTURESNUM(self.string);
            NSInteger videos = VIDEOSNUM(self.string);
            //Line below causes a leak
            [[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];
        }

        [self.string release];
    }

提前致谢!

修改

这是我的财产声明。

@property (nonatomic, retain) NSArray *filteredArray;
@property (nonatomic, retain) NSMutableArray *sectionArray;
@property (nonatomic, retain) UISearchBar *searchBar;
@property (nonatomic, retain) UISearchDisplayController *searchDC;
@property (nonatomic, retain) NSString *toUseFile;
@property (nonatomic, retain) NSArray *rawCrayons;
@property (nonatomic, retain) NSString *string;

@property (nonatomic, retain) TermViewController *childController;

以下是Nick Weaver修复后发生的泄漏事件。 Memory Leaks

这是NSCFString之一的扩展版本。 Memory Leaks in Depth

另一张图片。 Another one in depth

带有责任来电者的图片:Responsible Caller

另外,因为这可能很有用,所以这里是Term的属性:

@property (nonatomic, retain) NSString *name;
@property (nonatomic) NSInteger numberAudio;
@property (nonatomic) NSInteger numberPictures;
@property (nonatomic) NSInteger numberVideos;

实施:

@implementation Term

@synthesize name, numberAudio, numberPictures, numberVideos;

- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
    self.name = [toSetName retain];
    self.numberAudio = audio;
    self.numberPictures = pictures;
    self.numberVideos = videos;

    return self;
}

- (NSString*)getName
{
    return [[name retain] autorelease];
}

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

@end

3 个答案:

答案 0 :(得分:2)

好的,试试这个改变版的Temp。我已经删除了getter,因为你已经通过合成了。您可以使用这样的getter来命名:

term.name

问题在于你如何设置名称:你想要一个名称的副本,并使用合成的setter设置它而不调用retain应该可以解决问题。当然,您可以使用名称的保留属性设置它,但是您应该省略保留,例如self.name = toSetName;。安装者会为你保留它。

@property (nonatomic, copy) NSString *name;
@property (nonatomic) NSInteger numberAudio;
@property (nonatomic) NSInteger numberPictures;
@property (nonatomic) NSInteger numberVideos;


@implementation Term

@synthesize name, numberAudio, numberPictures, numberVideos;

- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
    self.name = toSetName;
    self.numberAudio = audio;
    self.numberPictures = pictures;
    self.numberVideos = videos;

    return self;
}

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

将对象添加到数组将保留实例,因此保留为2是因为您调用了

[[Term alloc] initToCall ..

执行类似

的操作
Term *term = [[Term alloc] initToCall..];

[theArray addObject:term];

[term release];

<强> 1。请参阅地址栏第一行中的箭头?点击它! enter image description here

<强> 2。点击后:): enter image description here

答案 1 :(得分:1)

很难告诉你为什么第一个泄漏,因为我们不知道该属性被宣告为什么。它保留了吗?复制?分配?什么?

最后一个是相当自我解释的,但是你拥有Term对象的所有权,而不是在添加它时释放它。 addObject:保留其参数,这意味着如果您不再需要该Term,则需要放弃所有权。即,将-autorelease传递给initToCall::::的结果(btw是一个非常糟糕的方法名称)

答案 2 :(得分:1)

变化:

[[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];

为:

Term *tempTerm = [[Term alloc] initToCall:NAME(self.string):audio:pictures:videos];
[[self.sectionArray objectAtIndex:firstLetter] addObject:tempTerm];
[tempTerm release];

通过分配一个对象,你负责释放它。