释放方法在运行时无法识别(非Cocoa)

时间:2013-02-24 01:56:27

标签: objective-c memory-management

我是Objective-C的新手,但在C和C ++方面拥有丰富的经验。我注意到的第一件事就是基本教程中存在一个真正的空白,因为所有人都假设您正在为iPhone或Mac开发并使用Cocoa。我没有使用Cocoa或Gnustep。要点:

作为开始的一个简单示例,我正在尝试包装C的文件I / O功能。我的代码以 File.h

#include <objc/Object.h>
#include <stdio.h>
@interface File:Object
{
    FILE *pFile;
    char *path;
}

@property FILE *pFile;
@property char *path;

- (void)new;
- (void)OpenReadText:(const char*)var1;
- (void)release;

@end

和File.m

#include "File.h"

@implementation File

@synthesize pFile, path;

- (void)new
{
    self = [super init];
}
- (void)release
{
    fclose(pFile);
    [super release];
}

- (void)OpenReadText:(char*)var1
{
    path = var1;
    pFile = fopen(path,"r");
}

@end

然后是main.m

#include <stdio.h>
#import <objc/Object.h>
#include "File.h"

int main(void) {

File *Fileobj = [File new];

[Fileobj OpenReadText:"File.h"];

[Fileobj release];


}

编译器给我一个警告,我的对象“可能不响应'-release'”。然后,当运行程序时会导致运行时错误:“无法识别释放。此应用程序已请求运行时终止”..等等。

我猜我正在制作一个简单的新手错误,但在哪里?或许还有什么遗失?我希望有人能指出我正确的方向。感谢。

如果已经问过这个qst那么参考也会这样做。我确实试图找到参考但没有运气。

关注:

将发布方法更改为

- (void)release
{
    fclose(pFile);
    [super free];
}

它似乎有效。显然,free会识别出object.h

3 个答案:

答案 0 :(得分:4)

正如其他人所说,在没有Foundation框架的情况下使用Objective-C是不寻常的。但是,Object类应该实现releaseretain等。在Apple的Objective-C运行时中包含(但未使用)的Object类当然包含这些基本方法。< / p>

假设您的Object类确实包含这些基本方法,那么您的类在实现时会遇到一些问题。

首先,您创建了一个new实例方法,只需调用[super init]即可。按惯例,new方法是一个类方法,它是调用allocinit来创建和初始化对象的简写。 new在Apple的Object课程中定义。它实现为:

+ (id)new
{
        id newObject = (*_alloc)((Class)self, 0);
        Class metaClass = self->isa;
        if (class_getVersion(metaClass) > 1)
            return [newObject init];
        else
            return newObject;
}

请注意,此方法是一种类方法,由+代替-表示。 GNUStep按如下方式实现new

+ new
{
   return [[self alloc] init];
}

使用new的惯用方法是:

File *obj = [File new];

这实际上是你所做的,但是,这是调用类方法new而不是实例方法new

如果您想拨打new方法,则必须致电:

File *obj = [[File alloc] new];

但正如其他人所说,你需要归还你的对象。删除新方法对您的实现没有影响,因为它当前没有被调用。

其次,您已在覆盖fclose方法中调用release。这是错误的,当然在Apple的Object实现中,GNUstep似乎有所不同。 release可以在一个对象的实例上多次调用。 retainrelease用于递增/递减对象保留计数。仅当保留计数达到零时,才应关闭文件句柄。通常情况下,您可以在基金会内以fclose方式拨打deallocdealloc是Objective-C的析构函数方法。 dealloc应该类似于:

- (void)dealloc
{
    fclose(pFile);
    [super dealloc];
}

但是,dealloc似乎没有在Apple或GNUstep的Object类中实现。正如您在问题中指出的那样,free方法似乎是一个析构函数。

似乎用等效的dealloc方法替换上面的free方法可以作为析构函数,例如:

- (void)free
{
    fclose(pFile);
    [super free];
}

Apple的Object实现包含retainrelease方法,但GNUstep实现却没有。这两种实现都不包含dealloc方法。

Apple和GNUstep的Object.mNSObject.m的实现可以在以下位置找到:

Apple Object.m:http://opensource.apple.com/source/objc4/objc4-532.2/runtime/Object.m

GNUstep Object.m:https://github.com/gnustep/gnustep-libobjc/blob/master/Object.m

Apple NSObject.mm:http://opensource.apple.com/source/objc4/objc4-532.2/runtime/NSObject.mm

GNUstep NSObject.m:https://github.com/gnustep/gnustep-base/blob/master/Source/NSObject.m

答案 1 :(得分:2)

release班上是否定义了Object?如果不是,那么请致电

[super release];

不起作用。 (在cocoa中,release是NSObject的成员;您的Object类可能有也可能没有,实际上保留/释放引用计数可能根本不存在。)

您应确认您的基类包含通过super调用的所有方法。

答案 2 :(得分:1)

正如@ xlc0212指出的那样,内存管理的引用计数风格包含在NSObject中。

NSObject是Cocoa,CocoaTouch和GnuStep的CoreFoundation库的一部分。我会说你需要链接到CoreFoundation。

我读过的一本关于纯Objective-C(不一定是Cocoa)的书是由Steven G Kochan撰写的“Objective-C 2.0编程”。