I've been studying the Objective-C runtime for some years, and even hacked libobjc a little bit (both Apple's and GNUStep's), and I've been wondering about a design decision on the compilers.
Every Objective-C object is expected to have its size at least of sizeof(Class)
, having its first field being Class isa
, as seem in struct objc_object
. We see it's explictly declared in root classes like NSObject
and old defunct Object
. We also know that the runtime adds the pointer to the new objects when they are created by class_createInstance()
(see code example below).
So, my question is: then why isn't the isa
pointer automatically prepended to the class declarations? Why does it need them to declare it explictly even if that is error-prone?
Example with bad code:
#import <stdlib.h>
#import <stdio.h>
#import <objc/runtime.h>
@interface Foo {
@public
int x;
};
- (void)bar;
@end
@implementation Foo
- (void)bar {
printf("bar\n");
};
@end
int main() {
Class cls = objc_getClass("Foo");
printf("cls = %p\n", cls);
// Returns sizeof(int)
printf("cls size = %ld\n", class_getInstanceSize(cls));
Foo *obj = class_createInstance(cls, 0);
printf("obj = %p\n", obj);
// Are we saving isa?
printf("hmm: %d\n", *((Class *)obj) == cls);
// We are! This works ;)
[obj bar];
// Evil code
obj->x = 10;
// Did we do something wrong?
printf("hmm: %d\n", *((Class *)obj) == cls);
// Yeah, we did! Segfault here!
[obj aaa];
return EXIT_SUCCESS;
};
isa
is not implicit in root classes... so I'd like to know if there is any. :)