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 @autoreleasepools 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 alloced 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 bools, which is malloced in init and freed 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!
Solution: Josh Caswell pointed out that my compiler flag fobj-arc should be fobjc-arc. Given that Clang gave no indicator of this flag being invalid, I'll leave this answer up for anyone else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With