目标c中的一个简单问题,关于内存泄漏

时间:2011-03-12 08:19:52

标签: objective-c memory-leaks autorelease nsobject

假设我有一个界面:

@interface it:NSObject
{
  NSString* string;
}
@end

@implement it
-(id)init
{
  if(self = [super init]){
    self.string = [[NSString alloc]init];
  }
}

-(void)dealloc
{
   [self.string release];
   [super release];
}
@end

如果我在另一个文件中使用此类,我称之为:

it ait = [[it allow] init];
NSString* anotherString = [[NSString alloc] init];
ait.string = anotherString;
[anotherString release];

这会导致在init方法中分配的字符串内存泄漏吗? 由于字符串未被引用而未自动释放。 如果我没有在init方法中分配一个字符串,那么当我在向它分配anotherString之前调用ait.string时会发生什么?

4 个答案:

答案 0 :(得分:1)

我认为你需要

@property (nonatomic, retain) NSString *string;

在您的界面中

@synthesize string;

在你的实现中使用self.string。

然后,当你做

self.string = [[NSString alloc] init];

在你的init方法中,字符串的实际保留计数为2,因为[[NSString alloc] init]将返回一个保留计数为1的字符串,并且使用self.string =将再次保留该对象,因为该属性是宣称为“保留”。这将导致内存泄漏,但您可以通过:

来解决
-(id)init
{
  if(self = [super init]){
    self.string = @"initString";
  }
}

或类似。

然后,在实际问题上,如果你按照上面的方式执行,当你用self.string =重新分配时,init中分配的字符串不会泄漏,因为标记为'retain'的属性会在保留新对象之前释放它们的当前对象。

如果你没有在init方法中为self.string分配一个字符串,那就无所谓了,因为self.string只返回nil,你可以在你的程序中处理它

答案 1 :(得分:0)

@interface it:NSObject
{
  NSString* string;
}

//you should declare a property in order to call it with 'self' prefix
@property (nonatomic, retain) NSString* string;

@end


@implementation it

//you should synthesize your property
@synthesize string;

-(id)init
{
  if(self = [super init]){
    //you don't to initialize NSString right here (memory leak will have place)
    //self.string = [[NSString alloc]init];

    //you can store a default value like this (can be omitted):
    self.string = @"Default value";
  }
  return self;
}

-(void)dealloc
{
   [self.string release];
   [super release];
}
@end

关于本课程内存管理的一切都会没问题。

答案 2 :(得分:0)

  

这是否会导致分配的字符串   init方法有内存泄漏吗?以来   字符串未被引用而不是   自动释放。

是的,确切地说。你似乎已经得到了它。

  

如果我没有在init中分配字符串   方法,我打电话会发生什么   在分配之前的ait.string   它的另一个字符串?

你的意思是在下面的例子中你不确定unknownObject会引用什么?: -

It *ait = [[It allow] init];
NSString *unknownObject = ait.string;

这是胡说八道。您是否忘记添加访问者方法?

Objective-c不使用“点语法”来访问实例变量,例如Java。如果你有一个类'it'的实例,你只能通过调用accessor'getter'方法从该实例外部访问'string'变量。这不是可选的self.string只是方法调用[self string]的快捷方式,并且在您显示的代码中不存在此方法。

假设访问器方法在别处定义,您调用字符串的实例变量(这是世界上最差的变量名称)等于 nil 。在Objective-c中,您必须非常小心地处理nil对象,因为行为与其他语言处理相似的 null 的行为不同。

在Objective-c中,这很好:

NSString *nilString = nil;
[nilString writeToFile:@"/this_file_cannot_exist.data"];

许多其他语言会在这里崩溃或抛出异常;这可能很危险,因为操作可能会失败但您的应用程序将继续运行。它也可能很棒,因为在其他语言中你会看到很多这个......

someObject = controller.currentValue()
if( someObject!=null )
  someObject.writeToFile("myFile.data")

在Objective-c中,根本不需要'if(..)'行。

您必须注意不要在init和dealloc方法中调用访问器方法,因为这会破坏子类。而不是

- (void)dealloc {
   [self.string release]; // This is [[self string] release]
   ...

你应该使用

- (void)dealloc {
   [string release];
   ...

除了危险之外,对[self string]的调用是不必要的。在init方法中也是如此

if(self=[super init]){
  self.string = [[NSString alloc]init]; // shortcut for [self setString:[[NSString alloc] init]]
  ...

只需使用

if(self=[super init]){
  string = [[NSString alloc] init];
  ...

答案 3 :(得分:0)

你错过了@property才能使用self.string。

将此添加到您的.h文件

@property (readwrite, copy) NSString *string;

使用Copy而不是Retain将阻止字符串内存泄漏,即使你释放了另一个字符串。