gpt4 book ai didi

objective-c - plist 文件加载的 NSDictionary 内存泄漏

转载 作者:行者123 更新时间:2023-12-03 21:23:14 25 4
gpt4 key购买 nike

我有一个内存泄漏问题,我无法理解!观看这个初始化方法:

- (id)initWithNomeCompositore:(NSString *)nomeCompositore nomeOpera:(NSString *)nomeOpera {

if (self = [super init]) {

NSString *pathOpere = [[NSBundle mainBundle] pathForResource:kNomeFilePlistOpere ofType:kTipoFilePlist];
NSDictionary *dicOpera = [NSDictionary dictionaryWithDictionary:
[[[NSDictionary dictionaryWithContentsOfFile:pathOpere]
objectForKey:nomeCompositore]
objectForKey:nomeOpera]];

self.nomeCompleto = [[NSString alloc] initWithString:nomeOpera];
self.compositore = [[NSString alloc] initWithString:nomeCompositore];
self.tipologia = [[NSString alloc] initWithString:[dicOpera objectForKey:kKeyTipologia]];
}

return self;}

然后这个小变化(注意 self.tipologia):

- (id)initWithNomeCompositore:(NSString *)nomeCompositore nomeOpera:(NSString *)nomeOpera {

if (self = [super init]) {

NSString *pathOpere = [[NSBundle mainBundle] pathForResource:kNomeFilePlistOpere ofType:kTipoFilePlist];
NSDictionary *dicOpera = [NSDictionary dictionaryWithDictionary:
[[[NSDictionary dictionaryWithContentsOfFile:pathOpere]
objectForKey:nomeCompositore]
objectForKey:nomeOpera]];

self.nomeCompleto = [[NSString alloc] initWithString:nomeOpera];
self.compositore = [[NSString alloc] initWithString:nomeCompositore];
self.tipologia = [[NSString alloc] initWithString:@"Test"];
}

return self;}

第一个变体会产生内存泄漏,第二个则不会!我就是不明白为什么! Instruments 证明了内存泄漏,突出显示了这一行:

[NSDictionary dictionaryWithContentsOfFile:pathOpere]

这是dealloc方法:

- (void)dealloc {
[tipologia release];
[compositore release];
[nomeCompleto release];
[super dealloc];}

最佳答案

请记住alloc返回您拥有的对象。

如果您将三个字符串属性声明为 retain ,将这些对象分配给您的属性意味着您现在拥有每个对象两次 - 一次是因为您分配了它,另一次是因为您将它分配给了您的属性。这些对象仍然存在,因为没有任何东西释放它们的第二所有权。

如果您将属性声明为 copy (这是声明 NSString 属性的正确方法),分配对象并将副本存储为属性的值。您无需对原始对象进行任何进一步操作,这些对象仍然存在,因为没有任何东西释放它们。

无论哪种方式,这都是你的泄漏。

该属性应声明为 copy ;如果已经存在,请不要尝试通过更改来修复泄漏。

您不应在此处使用属性访问。请记住,分配给属性是 set<PropertyName>:消息,并且您的对象尚未完全初始化。向未完全初始化或未完全释放的对象发送消息会带来麻烦,特别是在涉及子类时,因为它们可能会以父类(super class)不希望的方式重写访问器方法。

所以,在 init只是,直接分配给实例变量。在 dealloc仅限,发送release消息直接发送到实例变量中的对象。在其他地方,请使用属性访问。

您也不应该使用allocinitWithString:这里。它会起作用,但惯例是发送 copy向您已有的对象发送消息,与属性相同。发送copy消息到您的输入字符串对象,然后将副本分配给您的实例变量。

当您确实使用属性访问时,请使用便捷构造函数(例如 stringWith…: ),因为这些返回的对象不属于您。当您将这些对象分配给您的copy时-声明的属性,您实际上将存储您拥有的副本。

另一种方法是使用 allocinitWithWhatever: ,然后立即autorelease在将该对象分配给属性之前;这种方式会创建一个您拥有的对象,然后立即放弃所有权,然后再将其分配给属性。

关于objective-c - plist 文件加载的 NSDictionary 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2887736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com