NSMutableDictionary 中的内存泄漏

Posted

技术标签:

【中文标题】NSMutableDictionary 中的内存泄漏【英文标题】:Memory leaks in NSMutableDictionary 【发布时间】:2010-08-08 11:53:53 【问题描述】:

我的编码包含内存泄漏,但不知何故我找不到泄漏。

泄漏为我指明了创建“ReportDetailItems”的方式

例如areaContainer = [[[ReportDetailItem alloc] init] autorelease];

我已经看了好几个小时了,我完全不知所措,报告泄漏的对象是“ReportDetailItem”,以及这些对象中包含的 NSMutableDictionary。

请指教。

------[ReportDetailItem.h

@interface ReportDetailItem : NSObject

    NSNumber *total;
    NSMutableDictionary *items;



@property (nonatomic, retain) NSNumber *total;
@property (nonatomic, retain) NSMutableDictionary *items;

- (NSString *)description;

@end

------[ReportDetailItem.m

@synthesize items, total;

- (id)init 
    if (self = [super init]) 
        self.items = [NSMutableDictionary dictionaryWithCapacity:0];
        DLog("Alloc: %d", [items retainCount]);
       


    return self;


- (NSString *)description 
    return @"ReportDetailItem";


- (void)release 
    [super release];


- (void)dealloc 
    [self.items release];
    [self.total release];

    items = nil;
    total = nil;

    [super dealloc];


@end

------[泄露代码

NSError *error;
NSArray *data = [self.managedObjectContext executeFetchRequest:request error:&error];
if (data == nil || [data count] == 0) 
    DLog(@"No data.")
 else 
    for (int i=0; i < [data count]; i++) 
        TaskEntity *task = [data objectAtIndex:i];

        NSString *areaKey = task.activity.project.area.title.text;
        NSString *projectKey = task.activity.project.title.text;
        NSString *activityKey = task.activity.title.text;


        ReportDetailItem *areaContainer;
        if (![dataSource objectForKey:areaKey]) 
            areaContainer = [[[ReportDetailItem alloc] init] autorelease];
         else  
            areaContainer = [dataSource objectForKey:areaKey];
        
        areaContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [areaContainer.total intValue])];
        [dataSource setObject:areaContainer forKey:areaKey];


        ReportDetailItem *projectContainer;
        if (![areaContainer.items objectForKey:projectKey]) 
            projectContainer = [[[ReportDetailItem alloc] init] autorelease];
         else 
            projectContainer = [areaContainer.items objectForKey:projectKey];
        
        projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
        [areaContainer.items setObject:projectContainer forKey:projectKey];


        ReportDetailItem *activityContainer;
        if (![projectContainer.items objectForKey:activityKey]) 
            activityContainer = [[[ReportDetailItem alloc] init] autorelease];
         else 
            activityContainer = [projectContainer.items objectForKey:activityKey];
        
        activityContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [activityContainer.total intValue])];
        [projectContainer.items setObject:activityContainer forKey:activityKey];

    

【问题讨论】:

好吧,我不会对 iphone 的东西进行编程,但你的 for 看起来不对。应该是这样的:for (int i=0; i&lt;=x;i++) ?! 你是对的:for (int i=0; i 【参考方案1】:

找到了,泄漏的位置是我分配“dataSource”的方式

---[泄漏


- (void)viewDidLoad 
    [super viewDidLoad];
    self.dataSource = [[NSMutableDictionary alloc] init];
    [self fetchData];

---[无泄漏


- (void)viewDidLoad 
    [super viewDidLoad];

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
self.dataSource = dict;
[dict release];

[self fetchData];

【讨论】:

您的第一次(泄漏)方法是正确的。只需要在最后抛出一个自动释放。 1 行 > 3 行。【参考方案2】:

我非常怀疑您将指针分配给 ReportDetailItem 的两种方式。你为什么要首先自动释放对象?如果不试试这个

ReportDetailItem *projectContainer;
        if (![areaContainer.items objectForKey:projectKey]) 
            projectContainer = [[ReportDetailItem alloc] init];  
        else 
            projectContainer = [[areaContainer.items objectForKey:projectKey] retain];
        
        projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
        [areaContainer.items setObject:projectContainer forKey:projectKey];

      if(projectContainer) 
       [projectContainer release];
       projectContainer = nil;
      

【讨论】:

感谢您的洞察力。我正在尝试自动释放,因为它们以某种方式泄漏了。如果我尝试你的建议,我会得到“*** -[ReportDetailItem release]: message sent to deallocated instance 0x6ed9ef0” 您是否尝试打破 [projectContainer release] 行?也许你得到一个空指针。在这种情况下修改上面的代码

以上是关于NSMutableDictionary 中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

释放数组时 NSMutableDictionary 中使用的对象的内存会发生啥?

javascript中的关闭和回调内存泄漏

美团外卖服务端的测试面试题居然泄……泄……泄……泄密了

美团外卖服务端的测试面试题居然泄……泄……泄……泄密了

OpenGL VBO 会泄漏内存吗?

NSMutableDictionary 中的更改未反映在父 NSDictionary 中