iPhone:自定义类和NSMutableDictionary中的内存泄漏

iPhone:自定义类和NSMutableDictionary中的内存泄漏,iphone,memory-leaks,nsmutabledictionary,Iphone,Memory Leaks,Nsmutabledictionary,我花了几天时间想弄清楚到底发生了什么。我已经阅读了大量的内存管理文档,听到“对于每一个alloc,你都需要一个版本”,我感到非常恶心——我知道这一点,但我仍然不明白为什么我的代码会产生内存泄漏 我正在编写一个简单的自定义类,其属性之一是NSMutableDictionary。基本上,它模仿XMLELement。我一辈子都搞不懂为什么字典的分配会导致内存泄漏。泄漏发生在设备和模拟器上-设备上有5处泄漏,模拟器上有20处泄漏 在声明和分配变量*tmp时发生泄漏。 在设置属性详细信息(名称和值)时也存

我花了几天时间想弄清楚到底发生了什么。我已经阅读了大量的内存管理文档,听到“对于每一个alloc,你都需要一个版本”,我感到非常恶心——我知道这一点,但我仍然不明白为什么我的代码会产生内存泄漏

我正在编写一个简单的自定义类,其属性之一是NSMutableDictionary。基本上,它模仿XMLELement。我一辈子都搞不懂为什么字典的分配会导致内存泄漏。泄漏发生在设备和模拟器上-设备上有5处泄漏,模拟器上有20处泄漏

在声明和分配变量*tmp时发生泄漏。
在设置属性详细信息(名称和值)时也存在泄漏

这让我快发疯了。请帮忙

守则的一部分:

@interface IMXMLElement : NSObject {

NSString *strElementName;
NSString *strElementValue;
NSMutableDictionary *dictAttributes;
}

@property (nonatomic, retain) NSString *strElementName;
@property (nonatomic, retain) NSString *strElementValue;
@property (nonatomic, retain) NSMutableDictionary *dictAttributes;

@end

@implementation IMXMLElement

@synthesize strElementName;  
@synthesize strElementValue;  
@synthesize dictAttributes;

-(id)initWithName:(NSString *)pstrName
{
    self = [super init];

    if (self != nil)
    {
        self.strElementName = pstrName;
        **LEAK NSMutableDictionary *tmp = [[NSMutableDictionary alloc] init];
        self.dictAttributes = tmp;
        [tmp release];
    }

    return self;
}

-(void)setAttributeWithName:(NSString *)pstrAttributeName  
andValue:(NSString *)pstrAttributeValue  
{  
    **LEAK [self.dictAttributes setObject:pstrAttributeValue forKey:pstrAttributeName];  
}

-(void)dealloc
{
    [strElementName release];
    [strElementValue release];
    [dictAttributes release];
    [super dealloc];    
}

用户可以使用以下代码访问此类:


NSString*strValue=[[NSString alloc]initWithFormat:@“测试值”]


在释放dictAttributes之前,请尝试[dictAttributes removeAllObjects]

编辑:

此外,您将获得正分配,因为您正在为“tmp”分配内存。内存将被保留,因为您现在有了来自属性的引用


然后,当您将元素添加到字典中时,您将获得更积极的分配,这些元素也需要分配,并由字典的内部引用保存在内存中

在释放dictAttributes之前,请尝试[dictAttributes removeAllObjects]

编辑:

此外,您将获得正分配,因为您正在为“tmp”分配内存。内存将被保留,因为您现在有了来自属性的引用


然后,当您向字典添加元素时,您将获得更积极的分配,这些元素也需要分配,并由字典的内部引用保存在内存中

典型语法是
NSMutableDictionary*tmp=[[NSMutableDictionary alloc]init]autorelease]

典型语法是
NSMutableDictionary*tmp=[[NSMutableDictionary alloc]init]autorelease]

当字符串作为属性时,将其声明为“复制”,而不是“保留”

  NSMutableDictionary *tmp = [[NSMutableDictionary alloc] init];
  self.dictAttributes = tmp;
  [tmp release];
以上内容是不必要的,请改为: (此自动释放对象的保留计数将自动递增)

在dealloc中,请执行以下操作: (保留计数将自动递减)

通常,对于属性,您只需将它们设置为nil,而不是显式地释放它们
因为get/setter会为您处理这个问题。

当您将字符串作为属性时,请将它们声明为copy,而不是retain

  NSMutableDictionary *tmp = [[NSMutableDictionary alloc] init];
  self.dictAttributes = tmp;
  [tmp release];
以上内容是不必要的,请改为: (此自动释放对象的保留计数将自动递增)

在dealloc中,请执行以下操作: (保留计数将自动递减)

通常,对于属性,您只需将它们设置为nil,而不是显式地释放它们

因为get/setter会为您处理这些问题。

不要对
NSString
属性使用
retain
。使用
copy
OK-我运行了仪器泄漏工具,但它给了我一个麻烦。问题是我调用类时没有释放xmlElement和strValue。我在运行构建和分析后发现了这一点。谢谢你的评论。仪器工具指向我所说的泄漏线路。此外,该设备发现的泄漏比模拟器少。苹果需要在Instruments工具上运行一个合适的泄漏分析器(用于模拟器)。我还有另外一个问题。谁负责使用抽象方法NSDictionary*mydictionary=[NSDictionary dictionaryWithCapacity]发布名为的dictionary对象?我会把答案告诉所有回答的人this@snow888在这种情况下,返回的对象将自动释放。此外,Objective-C中没有抽象方法。不要将
retain
用于
NSString
属性。使用
copy
OK-我运行了仪器泄漏工具,但它给了我一个麻烦。问题是我调用类时没有释放xmlElement和strValue。我在运行构建和分析后发现了这一点。谢谢你的评论。仪器工具指向我所说的泄漏线路。此外,该设备发现的泄漏比模拟器少。苹果需要在Instruments工具上运行一个合适的泄漏分析器(用于模拟器)。我还有另外一个问题。谁负责使用抽象方法NSDictionary*mydictionary=[NSDictionary dictionaryWithCapacity]发布名为的dictionary对象?我会把答案告诉所有回答的人this@snow888在这种情况下,返回的对象将自动释放。此外,在Objective-C中不存在抽象方法这类东西。这种alloc/init/assign-to-property/release模式很常见,尤其是在Apple示例代码中。我在某个地方读到,autorelease不应该用于iPhone项目——这是正确的吗?我的意思是,不知道什么时候该对象会被释放,也不知道在你需要的时候它会被释放(尤其是当从函数/方法返回对象时。苹果的文档说你不应该使用autorelease,但文档的其余部分却充满了它。不一定。这种alloc/init/assign to property/release模式很常见,尤其是在苹果的示例代码中。我在某个地方读到autorelease不应该用于iPhone projects-这是正确的吗?我的意思是,不知道什么时候该对象会被释放,也不知道在你需要的时候它会被释放(特别是当从函数/方法返回对象时。苹果的文档说你不应该使用autorelease,但文档的其余部分都充满了它。好主意-我假设当你发布一个NSDictionary时,它的所有对象都会被释放-就像NSArray一样。好主意-我假设当你发布一个NSDictionary时,它的所有对象都会被释放ts对象也被释放-根据NSArray。不释放的原因是什么
self.dictAttributes = [NSMutableDictionary dictionaryWithCapacity:0];
self.dictAttributes = nil;