【问题标题】:[NSDate descriptionWithLocale:[NSLocale systemLocale]] leak?[NSDate descriptionWithLocale:[NSLocale systemLocale]] 泄漏?
【发布时间】:2011-09-28 22:36:06
【问题描述】:

Using instruments 我发现了一个关于内存泄漏的奇怪问题。我的应用程序有一个日志机制,它通过应用程序记录事件以及与服务器的整个通信(请求-响应)。每个被写入的事件对象都有一个时间戳。这个时间戳得到如下:

[NSDate descriptionWithLocale:[NSLocale systemLocale]]

使用工具,我看到 descriptionWithLocale 导致泄漏。

下面是代码:

-(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
     eventString = [[NSMutableString alloc] initWithString:eventStr];
     detailsString = [[NSString alloc] initWithString:detailsStr];
     date =[[NSMutableString alloc] init];
     NSDate* currentDate = [NSDate date];    
     NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
      [date appendString:dateDescStr];  

    return [super init];

谢谢, 亚历克斯。

【问题讨论】:

    标签: objective-c memory-leaks nsdate instruments


    【解决方案1】:

    您确定是descriptionWithLocale 导致了您的内存泄漏吗?您没有使用属性访问器/修改器来设置您的类属性,而是在 dealloc 方法以外的方法中释放它们,这将导致问题。至少,通过在initEvent 中分配eventStringdetailsStringdate(这是所有者,因为您不使用属性访问器/突变器),您至少违反了基本内存管理规则并在不是所有者的eventDictionary 方法中释放它们。

    我会先尝试以下方法(假设您的所有属性都具有retain 属性):

    -(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
         this.eventString = [[NSMutableString alloc] initWithString:eventStr];
         this.detailsString = [[NSString alloc] initWithString:detailsStr];
         this.date =[[NSMutableString alloc] init];
         NSDate* currentDate = [NSDate date];    
         NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
          [date appendString:dateDescStr];  
         [eventString release];
         [detailsString release];
         [date release];
    
        return [super init];
    }
    

    根据标准内存管理模式,还可以从 eventDictionary 中删除您的发布调用并将它们添加到 dealloc 方法。

    试试看是否有帮助。如果我能澄清任何事情,请告诉我。

    【讨论】:

      【解决方案2】:

      感谢您的解决方案。它工作得很好。确实不是 descriptionWithLocale 是泄漏的原因,而是我自己的内存规则实现(是 1 年前:( )。奇怪的是仪器指出了那个方法调用....看看我的班级现在的样子:

      @implementation EventItem
      @synthesize eventString, detailsString, date;
      
      
      -(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
      
          if((self = [super init])){
            self.eventString = [[NSMutableString alloc] initWithString:eventStr];
            self.detailsString = [[NSString alloc] initWithString:detailsStr];
            self.date =[[NSMutableString alloc] init];
            NSDate* currentDate = [NSDate date];    
            NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
            [date appendString:dateDescStr];      
            [eventString release];
            [detailsString release];
            [date release];
        }
      
        return self;
      }
      
      -(NSMutableDictionary*)eventDictionary{
          if(!dictionary)
             dictionary = [[NSMutableDictionary alloc] init];
          else
              return dictionary;
      
         [dictionary setObject:self.date forKey:@"Event"];
         [dictionary setObject:self.date forKey:@"Date"];
         [dictionary setObject:self.detailsString forKey:@"Details"];
         [dictionary setObject:self.eventString forKey:@"EventDescription"];
      
         return [dictionary autorelease];
       }
      
      -(void)dealloc{     
          // NSLog(@"dealloc called in EventItem");
      
         [eventString release];
         [detailsString release];
         [date release];
      
         [super dealloc]; 
      }
      
      
      @end
      

      现在,我遇到的另一个问题是关于通过“loadWithContentsOfFile:”加载的某些图像

      - (void)viewDidLoad {
          [super viewDidLoad];
      
          self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
          self.tableView.rowHeight = OC_CELL_HEIGHT;
          self.tableView.backgroundColor = [UIColor clearColor];
      
          UIImage* backgroundImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"TableBg" ofType:@"png"]];
          UIImageView* background = [[UIImageView alloc] initWithFrame:self.tableView.frame];
          background.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
          background.image = backgroundImage;
          [background sizeToFit];
          [backgroundImage release];
          [self.tableView setBackgroundView:background];
          [background release];
          [self.tableView setAutoresizesSubviews:YES];
          selectedOCData = nil;
          self.tableView.autoresizingMask =  UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;
      }
      

      行:

       UIImage* backgroundImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"TableBg" ofType:@"png"]];
      

      泄漏 98%,最大的回溯是 240 kb。我为此附上了一张带有仪器的屏幕截图。是不是 initWithContentsOfFile 的实际调用有问题,而是 tableView 没有正确释放?(我的类是 tableViewController)。

      谢谢, 亚历克斯。

      【讨论】:

      • 仅凭该代码很难分辨,但看起来基本正确。由于您将tableView 视为类属性,因此请确保在dealloc 方法中取消分配tableView。如果您需要更深入的帮助,我建议您提出一个新问题。
      猜你喜欢
      • 2023-03-16
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      • 2011-11-02
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多