首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态分析器显示错误泄漏??(XCode 4.0、iOS 4.3及以上)

静态分析器显示错误泄漏??(XCode 4.0、iOS 4.3及以上)
EN

Stack Overflow用户
提问于 2011-11-03 06:18:31
回答 2查看 862关注 0票数 2

祝大家十一月快乐,

我试着在我的项目上构建和分析Xcode,它显示了一些不寻常的漏洞,我对目标C的了解无法接受这些漏洞。

所以我决定做个测试项目然后在这里问。

MemoryTestController.h

代码语言:javascript
复制
@interface MemoryTestController : UIViewController{
  UIImageView *tstImageView;
}
@property(nonatomic,retain) UIImageView *tstImageView;
@end

MemoryTestController.m

代码语言:javascript
复制
@implementation MemoryTestController
@synthesize tstImageView;

- (void)viewDidLoad{
  [super viewDidLoad];

  self.tstImageView  = [[UIImageView alloc] //<==This object is leaking
                           initWithFrame:<SomeFrame>]; 
  self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
  [self.view addSubview:tstImageView];
  [tstImageView release];
}

-(void)dealloc{
  [tstImageView release];
  [super dealloc];
}
@end

当我尝试构建和分析时,clang静态分析器说

第xx行对象的

潜在泄漏

罪魁祸首是

代码语言:javascript
复制
self.tstImageView  = [[UIImageView alloc]initWithFrame:<SomeFrame>];

我想我每次分配/保留时都会释放一次。我是不是漏掉了什么,还是静态分析器有错误?

编辑:那里有漏洞吗?

嗯,我使用instrument..It中的泄漏工具运行了上面的项目,尽管我尝试了很多times..Whom,但没有显示任何泄漏,我应该相信吗?静电分析仪还是检漏仪器?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-03 06:24:45

你的问题在于你如何释放它:

代码语言:javascript
复制
- (void)viewDidLoad{
  [super viewDidLoad];

  self.tstImageView  = [[UIImageView alloc] //<==This object is leaking
                           initWithFrame:<SomeFrame>]; 
  self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
  [self.view addSubview:tstImageView];
  [tstImageView release]; // << here
}

你应该这样做:

代码语言:javascript
复制
- (void)viewDidLoad{
  [super viewDidLoad];

  UIImageView * imageView  = [[UIImageView alloc] initWithFrame:<SomeFrame>]; 
  imageView.image = [UIImage imageNamed:@"SomeImage.png"];
  self.tstImageView  = imageView;
  [imageView release];
  [self.view addSubview:self.tstImageView];
}

检查器是正确的,因为它不能假定变量与您设置的变量相同。因此,在OP中使用的表单可能会导致引用计数不平衡,因为当您在ivar上发布消息时,ivar的值可能不是您分配给它的值。

这些情况不太可能适用于UIImageView,在您的程序上下文中也不太可能,但是这些示例应该让您了解为什么检查器假定对象->ivar关联是不可信的:

在创建图像视图和通过ivar发布它的消息之间,您有:

代码语言:javascript
复制
  self.tstImageView  = [[UIImageView alloc] initWithFrame:<SomeFrame>]; 
  self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
  [self.view addSubview:tstImageView];

1)通过设置器分配图像视图;2)通过getter访问图像视图;3)在添加到self.view时,直接访问ivar。

  • -- setter可能已复制或使用了缓存的值。UIImageView是一个不好的例子,但是检查器不知道类型通常是如何传递的,即使它传递了类型,它也会(有时)做出不安全的假设。

最简单的例子是:

代码语言:javascript
复制
- (void)setName:(NSString *)inName {
  NSString * prev = name;
  if (inName == prev) return;
  if (0 == [inName count]) name = @"";
  else name = [inName copy];
  [prev release];
}

在此期间,ivar持有的价值

  • 可能会发生变化。在本例中不太可能出现问题,但假设将图像视图添加为子视图可能会在添加子视图的过程/效果中回调并更改self,并替换或删除您传递的图像视图。在这种情况下,您传递的变量视图会泄漏,它替换的视图将出现负不平衡。

在您的示例中,这两种情况都不太可能发生,但在实际的程序中确实会发生这种情况,而且检查器是基于本地而不是属性正确地进行计算的(检查器不能承担方法调用中发生的大量事情)。在这种情况下,它还鼓励了一种良好的习惯风格。

编辑:那里有漏洞吗?

嗯,我使用instrument..It中的泄漏工具运行了上面的项目,尽管我尝试过很多times..Whom,但它并没有显示任何泄漏。静电分析仪还是检漏仪器?

静态分析器表示存在潜在的泄漏,因为它无法保证它所遵循的引用/分配被正确保留/释放。您可以保证引用计数是正确的,并通过将程序更改为我在示例中编写的程序来满足静态分析器的要求。

你写它的方式使分析器无法跟踪参考文献。

如果你没有泄密和僵尸,那就没有泄漏。但是这个解决方案很容易修复--而且程序在开发过程中有一种改变的方式。使用我发布的表单要容易得多,所以工具集和验证程序是否正确更容易。静态分析器并不总是正确的,但是您应该调整程序以满足它,因为静态分析非常有用。我发布的程序对人类来说也更容易理解和确认它是正确的。

票数 5
EN

Stack Overflow用户

发布于 2011-11-03 06:24:17

当您像下面这样声明保留的属性时

代码语言:javascript
复制
@property(nonatomic,retain) UIImageView *tstImageView;

添加一个设置器,在分配属性时会增加retainCount。当您在下面这样做时,您创建的对象已经有一个retainCount == 1

代码语言:javascript
复制
self.tstImageView  = [[UIImageView alloc] 
                           initWithFrame:<SomeFrame>];

所以tstImageView对象在retainCount中有2。

做代替

代码语言:javascript
复制
UIImageView* view = [[UIImageView alloc] initWithFrame:<SomeFrame>];
self.tstImageView  = view;
[view release];

然后,尽管与您的泄漏无关,但是当您释放它时,可以像这样写

代码语言:javascript
复制
self.tstImageView = nil;

因为设置器将正确地设置retainCount

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

https://stackoverflow.com/questions/7990977

复制
相关文章

相似问题

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