释放对象的问题

时间:2009-06-30 15:51:52

标签: objective-c cocoa cocoa-touch

我有这段代码:

Entry.h

#import <Foundation/Foundation.h>

@interface Entry : NSObject {
    id object;
    SEL function;
}

@property (retain) id object;
@property (assign) SEL function;

-(Entry*) initWithObject:(id)object selector:(SEL)function;

@end

Entry.m

#import "Entry.h"

@implementation Entry

@synthesize object;
@synthesize function;

-(Entry*) initWithObject:(id)obj selector:(SEL)sel {
    self = [super init];
    [self setObject:obj];
    [self setFunction:sel];
    return self;
}

-(void) dealloc {
    [super dealloc];
    if ([self object] != nil)
        [[self object] release];
}

@end

当我这样做时:

Entry *hej = [Entry alloc];
[hej release];

我明白了:

objc[2504]: FREED(id): message object sent to freed object=0xf5ecd0
Program received signal:  “EXC_BAD_INSTRUCTION”.

我做错了什么?

(这个插件代码在堆栈溢出时不起作用,除非我做错了什么并且你不应该点击“代码示例”然后粘贴。)

5 个答案:

答案 0 :(得分:7)

+alloc仅分配内存。您需要-init才能在该内存空间中实际创建对象。由于您只是分配内存而不是在那里创建对象,因此在一块内存上调用-release会给您一个错误。此外,您希望[super dealloc]调用显示在-dealloc方法的末尾。改变这两件事,以下内容应该有效:

Entry *hej = [[Entry alloc] init];
[hej release];

答案 1 :(得分:3)

这里有两个问题:

1)你需要检查self = [super init]是否没有返回nil。典型的用法是使用条件包装初始化代码:

if ((self = [super init]) != nil) {
    // initialize the object...
}

2)但是你遇到的问题是实例化你的对象:你应该这样做:

Entry *hej = [[Entry alloc] initWithObject:myObj selector:mySelector];

(假设您想要浏览刚刚定义的自定义初始化程序... 否则只使用默认的init方法。)但是'alloc'必须后跟一个init。

Entry *hej = [[Entry alloc] init]; // will do the trick...

答案 2 :(得分:1)

首先,你需要一个init来配合你的。其次,在dealloc中,您在致电[super dealloc]后向自己发送消息。你不能这样做。最后的解除分配应该在最后。

答案 3 :(得分:1)

我还建议改变:

if ([self object] != nil)
    [[self object] release];

为:

[self setObject:nil];

它的代码和功能相同。 =)

答案 4 :(得分:0)

您的代码有很多问题。我会尝试通过它们。

首先,最好在属性名称中使用不同的ivar名称,以便清楚地显示每个名称。 Apple通常使用下划线前缀,但任何前缀都可以。

@interface Entry : NSObject {
    id _object;
    SEL _function;
}

@property (retain) id object;
@property (assign) SEL function;

@synthesize object = _object;
@synthesize function = _function;

接下来,您没有使用标准的init模板(虽然这通常不会产生任何影响)。

-(Entry*) initWithObject:(id)obj selector:(SEL)sel {
    self = [super init];
if (self != nil) {
    // initializations
}
    return self;
}

接下来,Apple(出于好的理由)建议不要在init / dealloc中使用getter / setter。所以你的init将是:

-(Entry*) initWithObject:(id)obj selector:(SEL)sel {
    self = [super init];
if (self != nil) {
    _object = [obj retain];
    _object = sel;
}
    return self;
}

接下来,在[super dealloc]之后你的对象被破坏了,所以你不能在那之后引用self(以及你的ivars),所以你的dealloc应该是这样的:

-(void) dealloc {
    // your deallocations
    [super dealloc];
}

此外,如上所述,Apple建议您不要在dealloc例程中使用setter或getter,因此您的释放最初应如下所示:

if (_object != nil)
    [_object release];

但更进一步,Objective C允许(和Cocoa鼓励)将方法发送到nil什么都不做。这与其他大多数消息都会导致崩溃的语言形成鲜明对比,但它是Objective C / Cocoa的工作方式,你需要习惯它。所以你的释放实际上只是:

[_object release];

最后,alloc只为你的对象分配内存,你必须初始化它,所以初始化将是这样的:

Entry *hej = [[Entry alloc] initWithObject:myobj selector:@selector(mymethod)];