首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >目标-C- NSMutableAttributedString泄漏

目标-C- NSMutableAttributedString泄漏
EN

Stack Overflow用户
提问于 2011-08-11 14:20:41
回答 3查看 1.7K关注 0票数 0

我是Obj的新手,我正在尝试一些东西。我偶然发现了一个泄漏问题,并想知道背后的逻辑原因。

下面的代码泄漏

代码语言:javascript
复制
(textViewAttrStr is an instance variable of type NSMutableAttributedString)

-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[textViewAttrStr appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[textViewAttrStr appendAttributedString:part2String];
[textViewAttrStr retain];

[part1String release];
[part2String release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

而下面的代码不会泄漏

代码语言:javascript
复制
-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[tvas appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[tvas appendAttributedString:part2String];

textViewAttrStr = tvas;
[textViewAttrStr retain];

[part1String release];
[part2String release];
[tvas release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

谁能解释一下原因吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-08-12 03:22:43

第二个例子显示,您不明白为什么在第一个示例中有漏洞,所以您可以选择进行实验,这似乎是一种可以理解的方法。

在第二个示例中,textViewAttrStr和tavs本质上是相同的。它们都是对内存中相同对象的引用(或指针)。

所以,当你这样做时:

代码语言:javascript
复制
textViewAttrStr = tvas;
[textViewAttrStr retain];
//...
[tvas release];

要在此对象上保留的调用与对该对象的释放调用是平衡的。这几乎什么都没做。在这里删除release和release提供了相同的功能。删除这些后,对象的引用计数为1,因为您调用了alloc,当dealloc命中时,它将达到0并被释放。

现在,在您的第一个示例中,您的对象正在分配(引用计数为1),然后保留(引用计数为2),当dealloc命中时,它将达到1的引用计数,而您的对象将不会被释放,从而泄漏。因此,这里的解决方案是删除要保留的调用。

顺便说一下,在向对象发送发布消息之前检查对象是否为零是不必要的,因为向nil发送消息没有任何作用。

票数 0
EN

Stack Overflow用户

发布于 2011-08-11 14:25:54

第一个例子的问题是额外的保留。您需要删除它,因为在用textViewAttrStr创建[[NSMutableAttributedString alloc] initWithString:@"Hello "];时,它已经被保留了。

代码语言:javascript
复制
//Remove this line in the first example
[textViewAttrStr retain];
票数 2
EN

Stack Overflow用户

发布于 2011-08-11 14:25:35

第一个例子:

代码语言:javascript
复制
textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
//...
[textViewAttrStr retain];

第二个例子

代码语言:javascript
复制
NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
//...
[tvas release];

现在您应该看到,在第一个示例中,您已经分配了/init并保留了它,哇。

第二个例子,您正确地分配了/init然后发布了。

简单的规则:如果你分配或复制或保留,你必须在某个时候释放。如果它是类变量,则在dealloc中释放,否则在离开作用域之前释放。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7027550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档