Objective-C/ARC/memory managements questions have been done to death on SO, but this one seems slightly different to the existing ones.
I've been trying to use Objective-C with GNUStep and Clang. I've downloaded the libraries
apparently required for modern Objective-C features like ARC; blocks work and @autoreleasepool
s are accepted by the compiler along with the associated compiler flag. The AppKit GUI toolkit works, and so does the queue dispatcher.
My understanding, if correct, is that alloc
ed objects are automatically set up to release upon the exiting of a @autoreleasepool
of a 'parent' stack frame, and that releasing decrements a reference count. Yet the compiler doesn't bemoan a manual [super dealloc]
and tolerates manual autoreleases
and releases
, which implies that ARC isn't even switched on.
One might imagine that Googling GNUStep ARC ~enable
would yield some compiler flag that I'm missing out, but it doesn't.
Here's some example code. It's an object wrapper around a multiple dimensional array of C99 bool
s, which is malloc
ed in init
and free
d within dealloc
, which I gather is one of the few legitimate uses of dealloc
within ARC code. Notice that dealloc
's puts
is not called after the @autoreleasepool finishes, despite there only being a single reference created within it. A manual release
or autorelease
, however, works great.
#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;
}
My compiling script (I'll use a proper makefile once I've got this working):-
#!/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
I've been under the assumption that autorelease
should be inferred for objects created within @autoreleasepool
.
Thanks in advance!
-fobj-arc
a typo here or in your actual script? – Meissner-fobjc-arc
– Meissneralloc
. I've also had to enable a 'non fragile ABI' via a flag. Thanks for the help; solved in the comments section... I've no answer to accept now. – Libyan