0

假设我有一个类名为MyTestClass.h当属性分配两次时避免内存泄漏

类结构是像

@implementation MyTestClass 

@synthesize testString;  

-(id) init{ 

    [self setTestString:@""];   
    return self; 
} 

-(void)dealloc{ 

    [self.testString release];  
    testString = nil; 

    [super dealloc]; 
} 

@end 

现在我创建的对象MyTestClass

@interface MyTestClass : NSObject { 

    NSString *testString; 
} 

@property (nonatomic, retain)NSString * testString; 

@end 

.m文件和分配的TestString两次

MyTestClass * myTestClass = [[MyTestClass alloc] init]; 

[myTestClass setTestString:@"Hi"]; 
[myTestClass setTestString:@"Hello"]; 

现在我想,两次我的testStrings内存泄漏! (1至的init(),另一个通过我的第一setTestString法)

,对吗?或将@property (nonatomic, retain)处理/释放先前分配的内存?

,或者在这种情况下,将我需要重写setTestString()MyTestClass.m如下面的代码

-(void)setTestString:(NSString *)tempString{  

    [testString release]; 
    testString = nil; 

    testString = [tempString retain]; 
} 

任何在这个问题上的帮助表示赞赏。

谢谢。

+0

你没有泄漏任何我能看到的 - 尽管我使用ARC。据我所知,如果你创建了一个赋值变量,然后在你的方法结束之前没有释放它,你只会在这种情况下泄漏。 – Dustin 2012-07-05 14:59:48

+0

请注意,在调用'super'之前,'dealloc'方法也可以简化为'self.testString = nil;',它将使用自动生成的setter自动释放之前的testString值。 – Turix 2012-07-05 15:02:33

+0

苹果文档特别声明不要在init和dealloc方法中使用访问器。希望引用文档,但目前无法找到它,这将不得不做的事情http://stackoverflow.com/questions/192721/why-shouldnt-i-use-objective-c-2-0-accessors-in- init-dealloc – 2012-07-05 15:08:43

回答

2

对这个问题的任何帮助表示赞赏。

我会拿这个作为许可证,让一些观测值不一定与你的问题直接相关。首先,如果你声明一个retain属性(如你所做的那样)并合成它,那么自动生成的getters和setter会正确地为你处理内存管理。

如果您手动创建setter(即使存在@synthesize也可以执行此操作),您必须自己进行内存管理。使用任一trojanfoe的例子。

在你的问题中的setter包含一个bug,如果testString == tempString,即您将属性的值分配给自己,您可能最终将一个悬挂指针分配给属性,因为您有效释放tempString,然后保留它。


这是一个安全忽略的实现细节,但是字符串文字例如@"blah"被编译到可执行文件中,无论释放多少次都不会被释放。所以,就你的例子来说,即使setter没有正确的内存管理,也不会有泄漏。


顺便说,对于init方法的正常模式是

-(id) init 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     // init stuff 
    } 
    return self; 
} 

或逻辑等效。

您应该养成使用它的习惯,因为您需要调用超类的init方法,并允许将self的值更改为nil。

另外,虽然在释放它之后通常将对象引用设置为零是非常好的做法,但在这两种情况下,当您这样做时,这是不必要的。第一次,变量即将超出范围,第二次您立即从其他对象分配变量。

0

这不是泄漏。正确处理合成变量。

内合成方法以这种方式实现的(对于保留关键字)

@property (nonatomic, retain) NSString *string; 
//backed by variable NSString *_string; 

- (void)setString:(NSString*)newString 
{ 
    if (newString != _string) { 
     [_string release]; 
     _string = [newString retain]; 
    } 
} 

当然,这是一个泄漏:

- (void)aMethod //of my class with string property 
{ 
    NSString *aString = [[NSString alloc] initWithString:@"hello"]; 
    self.string = aString; //retain count of 2 
    self.string = @"hello2"; //retain count of 1 for aString 

    //now I don't release aString.... leak 

} 
+0

@property(nonatomic,retain)将处理/释放先前分配的内存。我不想实现setTestString方法。我对吗? – 2012-07-05 15:22:47

+0

是的..你不需要实现它。我只是为了向你展示它是如何实现这个方法的(以及它是如何在引入属性之前实现的......)...所以..只需写一对'@ property'和'@ synthesize',你就是好! – Francesco 2012-07-05 15:29:25

0

如果使用自动生成的制定者(在你的的情况下,setTestString:,也称为self.testString = ...;),retain属性的先前值在被设置之前被释放。所以不,上面的代码没有泄漏。

0

synthesize d setter方法应该做正确的事情。下面是它的实现的例子:

- (void)setTestString:(NSString *)tempString 
{  
    [tempString retain]; 
    [testString release]; 
    testString = tempString; 
} 

或:

- (void)setTestString:(NSString *)tempString 
{  
    if (tempString != testString) 
    { 
     [testString release]; 
     [tempString retain]; 
     testString = tempString; 
    } 
} 
+0

实际使用的是最底层的。要么是有效的,但底部的一个给你一个边际性能的好处,因为如果tempString == testString没有昂贵的保留和释放完成。 – JeremyP 2012-07-05 15:01:52

+0

@JeremyP同意。你提到 – trojanfoe 2012-07-05 15:03:36

+0

@property(nonatomic,retain)将不处理/释放先前分配的内存。我必须实现setTestString方法来管理内存。我对吗? – 2012-07-05 15:25:00

0

当实例被破坏了的dealloc只调用。 如果你这样做:

[myTestClass setTestString:@"Hi"]; 
[myTestClass setTestString:@"Hello"]; 
在同一块

,你中庸之道调用二传手的两倍。没有内存泄漏。

0

当您在指定retain的属性上使用@synthesize时,生成的setter将正确处理多个赋值的保留/释放。只要你使用self.而不是直接进入后备变量,并在dealloc中做最后的发布,你应该没问题。