Xcode"分析"消息混淆

时间:2017-11-21 08:11:16

标签: ios objective-c xcode

我继承了一个不使用ARC的旧Objective C项目,并且由于第三方库的使用,可以使用ARC。

我试图解决因访问un / deallocated内存导致的一些随机崩溃。

我的首要任务之一是运行Xcode"分析"工具,看看它发现了什么问题。在大多数情况下,解决这些问题非常有用且最常见。

但是,我有一些课程(即自定义UITableViewCell)引起了一些关注,我不知道如何解决这些问题

Potential leak of an object

实际课程

#import "userListView.h"

@implementation userListView
@synthesize userCustomCelltextlabel,userCustomDetailtextlabel;
@synthesize unreadIdentifierImg;

-(void)dealloc {
  [userCustomCelltextlabel release];
  [userCustomDetailtextlabel release];
  [unreadIdentifierImg release];
  [super dealloc];
}


- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
  self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  if (self) {

    self.unreadIdentifierImg=[[UIImageView alloc]initWithFrame:CGRectMake(165,1,12,38)];

    self.userCustomCelltextlabel=[[UILabel alloc]initWithFrame:CGRectMake(12,5,150,20)];
    self.userCustomCelltextlabel.font=[UIFont fontWithName:@"TrebuchetMS-Bold" size:13.0f];
    self.userCustomCelltextlabel.backgroundColor=[UIColor clearColor];

    self.userCustomDetailtextlabel=[[UILabel alloc]initWithFrame:CGRectMake(12,22,150,15)];
    self.userCustomDetailtextlabel.backgroundColor=[UIColor clearColor];
    self.userCustomDetailtextlabel.textColor=[UIColor grayColor];
    self.userCustomDetailtextlabel.font=[UIFont fontWithName:@"Trebuchet MS" size:12.0];

    self.userCustomDetailtextlabel.numberOfLines=1;
    self.userCustomDetailtextlabel.lineBreakMode=NSLineBreakByTruncatingTail;


    //self.unreadIdentifierImg.image=[UIImage imageNamed:@"MessageEntrySendButton.png"];
    //self.unreadIdentifierImg.hidden=YES;
    [self.contentView addSubview:self.unreadIdentifierImg];

    [self.contentView addSubview:self.userCustomDetailtextlabel];
    [self.contentView addSubview:self.userCustomCelltextlabel];


  }
  return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
  [super setSelected:selected animated:animated];

  // Configure the view for the selected state
}

@end

标题

#import <UIKit/UIKit.h>

@interface userListView : UITableViewCell

@property (retain, nonatomic) UILabel *userCustomCelltextlabel;
@property (retain, nonatomic) UILabel *userCustomDetailtextlabel;

@property (retain, nonatomic) UIImageView *unreadIdentifierImg;

@end

扩展错误显示......

// 2. Method returns an instance of UIImageView with a +1 retain count
self.unreadIdentifierImg=[[UIImageView alloc]initWithFrame:CGRectMake(165,1,12,38)];
// Seems to point to UIImageView init

// 3. Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1
self.userCustomCelltextlabel=[[UILabel alloc]initWithFrame:CGRectMake(12,5,150,20)];
// Which seems to point to the UILabel init

重复userCustomDetailtextlabel。我在这里遇到的问题是allocated object is not referenced later in this execution path,因为它已添加到contentView,所以不是真的。

现在,显然,我们希望将对象保留为类的属性,并且只在取消分配对象时才处理它们,但我似乎无法对消息做出正面或反面。

我应该忽略它们吗?还有什么我应该考虑尝试解决它们吗?

2 个答案:

答案 0 :(得分:2)

使用retain声明属性,因此编译器将生成一个保留值的setter方法。

您使用alloc / init创建标签,为您提供保留计数为+1的标签,然后使用self.userCustomCelltextlabel将其分配给您的属性,这将调用发送保留的相应setter方法标签,现在它的保留计数为+2。

在dealloc中,您发送版本,标签的保留计数为+1并且正在泄漏。

autorelease添加到您的alloc / init或直接使用_userCustomCelltextlabel将其分配给ivar。

答案 1 :(得分:2)

如果这是您第一次在Objective-C中遇到手动内存管理 - 也称为&#34;手动保留释放&#34; - 如果这个项目无法迁移到ARC,那么我只能建议您花时间学习手动内存管理。 the Cocoa Core Competencies guide中的Memory-Management页面和the Advanced Memory Management Programming Guide中的Practical Memory Management页面是两个很好的起点。

不幸的是,整个手动内存管理太大而不适合Stack Overflow的答案,但我会解释其中一个对象发生了什么 - 在这一行:

self.unreadIdentifierImg = [[UIImageView alloc] initWithFrame:CGRectMake(165,1,12,38)];

当你致电[[UIImageView alloc] initWithFrame: ... ];时,你会分配内存并创建一个新对象。根据Cocoa 所有权政策,您拥有&#34;拥有&#34;自从您调用alloc以来,此对象负责其内存。此时,这个新创建的对象的保留计数为1。

当您将该对象分配给self.unreadIdentifierImg时,它将保留分配给它的对象。发生这种情况是因为该属性定义为@property (retain, nonatomic) ...。这保留了对象保留计数,这意味着它现在处于2。

由于图像视图既未保留也未在该范围的其余部分中释放,因此最终得到的图像视图的保留计数为2(一个来自创建时,一个来自引用它的属性)。

稍后当取消分配单元格并释放图​​像视图(显式调用release或将属性设置为nil)时,图像视图的保留计数会减少,这意味着它现在处于1 (从创建时起)由于没有对此图像视图的其他引用,并且由于它的保留计数不为0,因此该对象现已泄露。

要修复它,您需要在将其分配到保留属性后将其释放一次。你最有可能通过&#34;自动释放&#34;来做到这一点。它,这意味着该对象将被添加到当前的自动释放池中 - 以便在池耗尽时释放:

self.unreadIdentifierImg = [[[UIImageView alloc] initWithFrame:CGRectMake(165,1,12,38)] autorelease];

请注意,该行末尾添加了autorelease次调用。

根据我的经验,当静态分析仪警告这样的事情时,它几乎总是正确的,因此建议仔细检查这些警告并彻底调查它们。