祝大家十一月快乐,
我试着在我的项目上构建和分析Xcode,它显示了一些不寻常的漏洞,我对目标C的了解无法接受这些漏洞。
所以我决定做个测试项目然后在这里问。
MemoryTestController.h
@interface MemoryTestController : UIViewController{
UIImageView *tstImageView;
}
@property(nonatomic,retain) UIImageView *tstImageView;
@endMemoryTestController.m
@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行对象的
潜在泄漏
罪魁祸首是
self.tstImageView = [[UIImageView alloc]initWithFrame:<SomeFrame>];我想我每次分配/保留时都会释放一次。我是不是漏掉了什么,还是静态分析器有错误?
编辑:那里有漏洞吗?
嗯,我使用instrument..It中的泄漏工具运行了上面的项目,尽管我尝试了很多times..Whom,但没有显示任何泄漏,我应该相信吗?静电分析仪还是检漏仪器?
发布于 2011-11-03 06:24:45
你的问题在于你如何释放它:
- (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
}你应该这样做:
- (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发布它的消息之间,您有:
self.tstImageView = [[UIImageView alloc] initWithFrame:<SomeFrame>];
self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
[self.view addSubview:tstImageView];1)通过设置器分配图像视图;2)通过getter访问图像视图;3)在添加到self.view时,直接访问ivar。
UIImageView是一个不好的例子,但是检查器不知道类型通常是如何传递的,即使它传递了类型,它也会(有时)做出不安全的假设。最简单的例子是:
- (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,但它并没有显示任何泄漏。静电分析仪还是检漏仪器?
静态分析器表示存在潜在的泄漏,因为它无法保证它所遵循的引用/分配被正确保留/释放。您可以保证引用计数是正确的,并通过将程序更改为我在示例中编写的程序来满足静态分析器的要求。
你写它的方式使分析器无法跟踪参考文献。
如果你没有泄密和僵尸,那就没有泄漏。但是这个解决方案很容易修复--而且程序在开发过程中有一种改变的方式。使用我发布的表单要容易得多,所以工具集和验证程序是否正确更容易。静态分析器并不总是正确的,但是您应该调整程序以满足它,因为静态分析非常有用。我发布的程序对人类来说也更容易理解和确认它是正确的。
发布于 2011-11-03 06:24:17
当您像下面这样声明保留的属性时
@property(nonatomic,retain) UIImageView *tstImageView;添加一个设置器,在分配属性时会增加retainCount。当您在下面这样做时,您创建的对象已经有一个retainCount == 1
self.tstImageView = [[UIImageView alloc]
initWithFrame:<SomeFrame>];所以tstImageView对象在retainCount中有2。
做代替
UIImageView* view = [[UIImageView alloc] initWithFrame:<SomeFrame>];
self.tstImageView = view;
[view release];然后,尽管与您的泄漏无关,但是当您释放它时,可以像这样写
self.tstImageView = nil;因为设置器将正确地设置retainCount
https://stackoverflow.com/questions/7990977
复制相似问题