【问题标题】:Unknown Memory Leak in iPhoneiPhone中的未知内存泄漏
【发布时间】:2011-04-03 20:22:09
【问题描述】:

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

这是代码,我已将 cmets 添加到它发生的两个地方。

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 的修复程序后发生的泄漏。

这里是 NSCFString 之一的扩展版本。

还有一张图片。

负责来电者的图片:

另外,因为这可能有用,这里是 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

【问题讨论】:

  • 了解rawCrayons 属性的定义方式可能会有所帮助。
  • @Jim Blackler 它在我发布的代码中,不是吗?
  • 我的意思是头文件中的定义,例如@property (nonatomic, retain) IBOutlet NSButton *myButton;
  • @Jim Blackler 我在上面添加了我的属性声明。

标签: iphone string memory-leaks autorelease


【解决方案1】:

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

term.name

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

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

给数组添加对象会保留实例,所以retain是2,因为你调用

[[Term alloc] initToCall..

做一些类似的事情

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

[theArray addObject:term];

[term release];

1.看到地址栏中第一行的箭头了吗?点击它!

2。点击后:)

【讨论】:

  • @Nick Weaver 我关注了这个,现在我在 NSCFString 上发现了一个漏洞,当我双击它时,它只是汇编代码。
  • 首先,将您的 NSString 属性从保留更改为复制:NSString 是不可变的,因此您需要它的副本,而不是可以通过某些进程在后台更改的内容。
  • 我的意见是:是的,我就是这样做的。如果您不将整本书存储在字符串中,则复制是 NSStrings 的正确选择。看看NSString property copy or retain,这很好地解释了差异。
  • 我不知道,你必须找出。这里的问题解决是迭代的,我没有运行代码,所以只能根据给定的信息帮助下一步。
  • 感谢新代码,我想我们已经接近解决方案了。看看我的答案更新。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    变化:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 2011-12-10
      • 2011-05-24
      • 2023-03-20
      • 1970-01-01
      相关资源
      最近更新 更多