iPhone 中的未知内存泄漏

发布于 2024-10-30 13:30:24 字数 2843 浏览 4 评论 0原文

我目前正在为 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 之一的扩展版本。 深度内存泄漏

还有另一张图片。 另一张深入的

负责呼叫者的图片: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

I am currently building an app for the iPhone and cannot figure out why I keep getting a memory leak to appear in the Leaks Instrument tool.

Here is the code and I have added comments to two places of where it is happening.

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];
    }

Thanks in advance!

Edit

Here are my property declarations.

@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;

Here are the leaks that are occurring after follow Nick Weaver's fixes.
Memory Leaks

Here is an expanded version of one of the NSCFString. Memory Leaks in Depth

And another image. Another one in depth

Image with the Responsible Caller: Responsible Caller

Also, because this may be useful, here are the properties for Term:

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

And the implementation:

@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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泪之魂 2024-11-06 13:30:25

好的,尝试这个更改后的 Temp 版本。我已经删除了吸气剂,因为你已经通过合成获得了吸气剂。您可以像这样使用 getter 作为名称:

term.name

问题是如何设置名称:您需要名称的副本并使用合成的 setter 设置它而不调用保留应该可以解决问题。当然,您可以使用 name 的保留属性来设置它,但您应该省略保留,例如 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 的操作。看到地址栏中第一行的箭头了吗?点击它!
在此处输入图像描述

2.点击后:)
在此处输入图像描述

Ok, try this changed Version of Temp. I've deleted the getter because you have already one by synthesizing. You cann use the getter like this for name:

term.name

The problem was how you set the name: you want a copy of the name and setting it with the synthesized setter without calling a retain should do the trick. You could, of course, have set it with the retained property of name but you should have left out retain, like this self.name = toSetName;. The setter will retain it for you.

@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];
}

Adding an object to an array will retain the instance, so the retain is 2 because you call

[[Term alloc] initToCall..

Do something like

Term *term = [[Term alloc] initToCall..];

[theArray addObject:term];

[term release];

1. See the arrow in the first line in the address column? Click it!
enter image description here

2. After clicking :)
enter image description here

乖乖兔^ω^ 2024-11-06 13:30:25

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

最后一个是相当不言自明的,您将获得 Term 对象的所有权,并且在添加它时不会释放它。 addObject:保留其参数,这意味着如果您不再需要该术语,则需要放弃所有权。即,将 -autorelease 传递给 initToCall:::: 的结果(顺便说一句,对于方法来说这是一个非常糟糕的名称)

Hard to tell you why the first one is leaking, because we don't know what the property is declared as. Is it retain? copy? assign? what?

The last one is fairly self explanatory though, you're taking ownership of a Term object, and not releasing it when it's added. addObject: retains its argument, meaning if you don't need that Term anymore, you need to give up ownership. I.e., pass -autorelease to the result of your initToCall:::: (which btw is a very bad name for a method)

十年不长 2024-11-06 13:30:25

更改

[[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];

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

Change:

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

to:

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

By alloc'ing an object you are responsible for it's release.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文