Skip navigation.
 
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
FROM : John Engelhart
DATE : Thu Feb 07 07:14:02 2008

On Feb 6, 2008, at 10:01 PM, glenn andreas wrote:

>
> On Feb 6, 2008, at 7:48 PM, John Engelhart wrote:

>> int main(int argc, char **argv) {
>> NSObject *stackObject = NULL;
>> stackObject = alloca(sizeof(stackObject));

>
> This, of course, just alloced something the size of a pointer, which 
> may not be the real size of the class (if it were something other 
> than NSObject)


Opps, you're right.  I clearly meant NSObject, as the memset line 
below shows.  You'll note that changing the alloca line from 
stackObject to NSObject works just fine.

>

>>
>> memset(stackObject, 0, sizeof(NSObject));
>> stackObject->isa = [NSObject class];
>>
>> NSLog(@"stackObject: %@", stackObject);
>> }
>> [<email_removed>] /tmp% gcc -framework Foundation -o tst tst.m
>> tst.m: In function 'main':
>> tst.m:7: warning: instance variable 'isa' is @protected; this will 
>> be a hard error in the future
>> [<email_removed>] /tmp% ./tst
>> 2008-02-06 20:17:16.306 tst[18320:807] stackObject: <NSObject: 
>> 0xbffff380>
>>
>> As the address clearly shows, this is an object on the stack. 
>> Although I have had to manually initialize the object, it is 
>> exactly, or very close to, what "NSObject stackObject" would have 
>> created.
>>
>>

>
> The biggest problem is that the above example shows something that 
> isn't usable - it's sterile.  You can't pass it to other routines 
> (due to memory management requirements), you may not even be able to 
> call all the methods of the object (since they may pass the 
> themselves as parameters to other objects  which invoke memory 
> management requirements).  Only if you wrote your own entire 
> hierarchies could you use such a construction (or if you implemented 
> full closures, which is even more difficult in a C based 
> language) .  There's a whole raft of semantics associated with Cocoa 
> objects (above and beyond anything that whatever version of the 
> objective-c runtime may require).


I'm pretty sure I was clear that this is "not really a good idea in 
reality."  It is, unlike you stated, possible to do.

>
> If you can't use the object, have you actually created it?


You can use the object.  It remains live until the stack frame pops. 
It will work exactly like any other object.  The "deallocation" of the 
object is tricky, but I'm sure you could still pull it off if you 
really wanted.

>>
>> As you can see, and the code clearly demonstrates, my original 
>> assertion stands.
>>

>
> One could also manually construct a C++ vtable and set up all the 
> magic "behind the scenes" plumbing that a C++ object has, but that 
> doesn't mean that C++ object are ' synonymous for "Structs" ' either.
>
> The point is that they are not synonymous for structs - if they 
> were, you could replace one with the other, and both Objective-C and 
> C++ objects have additional semantic requirements.


You can replace one for the other, see above.  The GCC compiler stops 
you from doing this because it's really not a good idea in practice. 
There are other Objective-C implementations that allow stack based 
objects exactly as you describe.  I can't remember which one it was 
off the top of my head, it might have been poc.

This is a literal "NSObject stackObject;", if it helps any:

#import <Foundation/Foundation.h>

int main(int argc, char **argv) {
  struct { @defs(NSObject) } stackObject;
  memset(&stackObject, 0, sizeof(NSObject));
  stackObject.isa = [NSObject class];

  NSLog(@"stackObject: %@", &stackObject);
}
[<email_removed>] /tmp% gcc -framework Foundation -o tst tst.m
[<email_removed>] /tmp% ./tst
2008-02-07 00:04:20.477 tst[18686:807] stackObject: <NSObject: 
0xbffff398>
[<email_removed>] /tmp%

I suppose I could go through all the trouble of putting together 
initialization and deallocation methods as part of a subclass, or 
category override, that specifically dealt with stack "allocation" and 
"deallocation".  I could even get crafty and have dealloc check to see 
if self is an pointer that's on the stack and call the stack dealloc 
code, and the standard dealloc code otherwise.

Honestly though, I'm not sure how much more plain I can make it.  You 
said:
>

>>
>> You misunderstand what Objective C is, and how it works.  "Objects" 
>> is synonymous for "Structs".

>
>
>
> If that were true, you'd be able to declare objects as local 
> variables (as opposed to as pointers to structures):
>
>     NSPoint aPoint; // <-- NSPoint = struct, legal
>     NSString aString; // <-- NSString = object, Illegal


Yet, as the code above plainly shows, "struct { @defs(NSObject) } 
stackObject;" has declared an object as a local variable, even passed 
to NSLog() to print its description, proving that's it's a bona-fide, 
useable object, and that the keyword "struct" makes it obvious that an 
"object" is just a "struct".

How about "Objects" is synonymous for "struct objc_object"s ?  And 
since struct objc_object is typedefed to "*id", that makes it pretty 
literal.

Does this help at all?

#import <Foundation/Foundation.h>

typedef struct { @defs(NSObject) } NSObject_;

int main(int argc, char **argv) {
  NSObject_ stackObject;
  memset(&stackObject, 0, sizeof(NSObject));
  stackObject.isa = [NSObject class];

  NSLog(@"stackObject: %@", &stackObject);
}
[<email_removed>] /tmp% gcc -framework Foundation -o tst tst.m
[<email_removed>] /tmp% ./tst
2008-02-07 00:28:47.784 tst[18734:807] stackObject: <NSObject: 
0xbffff398>

I've had to add an underscore to prevent namespace collision, but.... 
I'm not really sure how else I can explain it.


>

>>
>> As you can see, it's very clear where "isa" comes from. 
>> Subclassing an object has the effect of "pasting" your ivar 
>> declarations at the end of the class you're inheriting from, and 
>> forms the cause of "fragile classes" since a struct effectively 
>> becomes pointer + offset, and changing a struct requires 
>> recompiling code to update those offsets.

>
> Except, of course, for 64 bit Objective-C 2.0 which doesn't have 
> these problems (which makes the exercise of trying to allocate it on 
> the stack even more problematic).


Yes, as I have noted, the ObjC 2.0 64 bit ABI/API is different.  This 
is dealing with the 32 bit version, which has been around since the 
80's.

>> So, no, there are no magic invisible members.

>
> But there are semanticly required members that aren't in "plain" 
> structs.


Honestly, I don't follow.  What is a "plain" struct?

struct objc_object {
  void *isa;
};

Is that not a "plain" struct?  And what do you mean by "semantically 
required members"?

#import <Foundation/Foundation.h>

typedef struct { char letters[4]; } NSObject_;

int main(int argc, char **argv) {
  NSObject_ stackObject;
  memset(&stackObject, 0, sizeof(NSObject_));
  void *classPtr = [NSObject class];
  memcpy(stackObject.letters, &classPtr, sizeof(void *));

  NSLog(@"stackObject: %@", &stackObject);
}
[<email_removed>] /tmp% gcc -framework Foundation -o tst tst.m
[<email_removed>] /tmp% ./tst
2008-02-07 00:37:57.632 tst[18799:807] stackObject: <NSObject: 
0xbffff398>

Sure, a bit of square peg in to a round hole abuse to get the class 
ptr copied over.... but.. No isa here, yet it works.

I suppose pedantically one could argue that in order for something to 
be an "object", it would have to have the layout of a particular kind 
of struct... but I think that's pushing things a little far, and in 
the end, whatever the layout, that layout is declared as a struct.

Related mailsAuthorDate
mlUse of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 4, 02:57
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Quincey Morris Feb 4, 05:09
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful j o a r Feb 4, 08:18
mlre: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Ben Trumbull Feb 4, 10:19
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Alastair Houghton Feb 4, 14:11
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Greg Titus Feb 4, 16:39
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Sean McBride Feb 4, 22:40
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 5, 01:14
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Chris Hanson Feb 5, 02:21
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Jonathon Mah Feb 5, 08:47
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Alastair Houghton Feb 5, 13:40
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 6, 10:39
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Alastair Houghton Feb 6, 12:15
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 6, 15:59
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Michael Tsai Feb 6, 16:12
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful glenn andreas Feb 6, 16:45
mlBug in CF/NSString's no-copy constructors (was Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful) Alastair Houghton Feb 6, 16:55
mlRe: Bug in CF/NSString's no-copy constructors (was Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful) Michael Tsai Feb 6, 17:46
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Clark Cox Feb 6, 17:47
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Jean-Daniel Dupas Feb 6, 18:05
mlRe: Bug in CF/NSString's no-copy constructors Alastair Houghton Feb 6, 18:46
ml[Moderator] Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Scott Anguish Feb 6, 18:46
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Hamish Allan Feb 6, 18:52
mlRe: Bug in CF/NSString's no-copy constructors Michael Tsai Feb 6, 19:29
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Hamish Allan Feb 6, 19:36
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Alastair Houghton Feb 6, 20:12
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful glenn andreas Feb 6, 21:23
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Sean McBride Feb 6, 21:47
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Michael Ash Feb 6, 22:38
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Hamish Allan Feb 6, 23:49
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 7, 02:06
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Hamish Allan Feb 7, 02:40
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Chris Suter Feb 7, 02:48
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 7, 02:48
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Clark Cox Feb 7, 03:52
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful glenn andreas Feb 7, 04:01
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Timothy Reaves Feb 7, 04:08
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Brady Duga Feb 7, 04:22
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 7, 07:14
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 7, 07:14
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Michael Ash Feb 7, 23:58
mlRe: Bug in CF/NSString's no-copy constructors John Engelhart Feb 8, 03:31
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful John Engelhart Feb 8, 05:23
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Greg Parker Feb 8, 05:30
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Michael Tsai Feb 8, 05:56
mlRe: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Hamish Allan Feb 8, 18:35
ml[Moderator] Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful Scott Anguish Feb 8, 22:17