【发布时间】:2013-11-22 15:07:51
【问题描述】:
Objective-C/ARC/内存管理问题已经在 SO 上做死了,但这一个似乎与现有的略有不同。
我一直在尝试将 Objective-C 与 GNUStep 和 Clang 一起使用。我已经下载了库
显然是现代 Objective-C 特性(如 ARC)所必需的;块工作和@autoreleasepools 与相关的编译器标志一起被编译器接受。 AppKit GUI 工具包有效,队列调度程序也有效。
如果正确,我的理解是alloced 对象会自动设置为在“父”堆栈帧的@autoreleasepool 退出时释放,并且释放会减少引用计数。然而编译器不会抱怨手动 [super dealloc] 并容忍手动 autoreleases 和 releases,这意味着 ARC 甚至没有打开。
人们可能会想象谷歌搜索 GNUStep ARC ~enable 会产生一些我错过的编译器标志,但事实并非如此。
这是一些示例代码。它是一个围绕 C99 bools 的多维数组的对象包装器,它是init 中的malloced 和dealloc 中的freed,我认为这是dealloc 的少数合法用途之一在 ARC 代码中。请注意dealloc 的puts 在@autoreleasepool 完成后不被调用,尽管其中只创建了一个引用。但是,手动 release 或 autorelease 效果很好。
#import <stdbool.h>
#import <stdio.h>
#import <stdlib.h>
#import <Foundation/Foundation.h>
@interface Area : NSObject {
bool *area;
size_t width, height;
}
- (id) initWithWidth:(size_t)aWidth height:(size_t)aHeight;
- (void) dealloc;
- (void) display;
@end
@implementation Area
- (id) initWithWidth:(size_t)aWidth height:(size_t)aHeight {
self = [super init];
width = aWidth;
height = aHeight;
area = malloc((sizeof *area) * aWidth * aHeight);
for (size_t y = 0; y < aHeight; ++y) {
for (size_t x = 0; x < aWidth; ++x) {
area[(aHeight * y) + (aWidth * x)] = true;
}
}
return self;
}
- (void) dealloc {
free(area);
puts("DEALLOCATED");
}
- (void) display {
for (size_t y = 0; y < height; ++y) {
putchar('|');
for (size_t x = 0; x < width; ++x) {
putchar(area[(height * y) + (width * x)]
? '#'
: ' ');
}
puts("|");
}
}
@end
int main(void)
{
@autoreleasepool {
id area = [[Area alloc] initWithWidth:10 height:10];
[area display];
}
return EXIT_SUCCESS;
}
我的编译脚本(一旦我完成了这个工作,我将使用适当的 makefile):-
#!/bin/sh
INC_FLAG=`gnustep-config --variable=GNUSTEP_SYSTEM_HEADERS`
LIB_FLAG=`gnustep-config --variable=GNUSTEP_SYSTEM_LIBRARIES`
clang -o main main.m \
-I $INC_FLAG \
-L $LIB_FLAG \
\
-fblocks \
-fobj-arc \
-fconstant-string-class=NSConstantString \
-D_NATIVE_OBJC_EXCEPTIONS \
\
-pthread \
-lgnustep-base \
-ldispatch \
-lgnustep-gui \
-lobjc
我一直假设 autorelease 应该被推断为在 @autoreleasepool 中创建的对象。
提前致谢!
【问题讨论】:
-
-fobj-arc是这里的错字还是在您的实际脚本中? -
不,它在脚本中。我认为如果它的参数无效,编译器会抱怨......
-
对我来说似乎是一个合理的假设,但绝对应该是@987654343@
-
啊哈!我现在完全可以工作了。我很惊讶我可以将无效的废话作为参数传递给clang,它只是默默地忽略它们而不是警告我。现在它已启用,它抱怨手动
alloc。我还必须通过标志启用“非易碎 ABI”。谢谢您的帮助;在 cmets 部分解决了...我现在没有答案可以接受。 -
很高兴你把它整理出来!如果其他人做同样的事情,我似乎不太可能特别发现这个问题。我建议只是将它发送到比特桶,但如果你愿意,你可以自己回答。
标签: objective-c memory-management automatic-ref-counting autorelease gnustep