• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful


  • Subject: Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
  • From: John Engelhart <email@hidden>
  • Date: Thu, 7 Feb 2008 01:14:02 -0500


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);
}
[johne@LAPTOP_10_5] /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
[johne@LAPTOP_10_5] /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);
}
[johne@LAPTOP_10_5] /tmp% gcc -framework Foundation -o tst tst.m
[johne@LAPTOP_10_5] /tmp% ./tst
2008-02-07 00:04:20.477 tst[18686:807] stackObject: <NSObject: 0xbffff398>
[johne@LAPTOP_10_5] /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);
}
[johne@LAPTOP_10_5] /tmp% gcc -framework Foundation -o tst tst.m
[johne@LAPTOP_10_5] /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);
}
[johne@LAPTOP_10_5] /tmp% gcc -framework Foundation -o tst tst.m
[johne@LAPTOP_10_5] /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.
_______________________________________________


Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: John Engelhart <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: Alastair Houghton <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: John Engelhart <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: Alastair Houghton <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: John Engelhart <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: glenn andreas <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: John Engelhart <email@hidden>)
 >Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful (From: glenn andreas <email@hidden>)

  • Prev by Date: Determining if a url exists
  • Next by Date: Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
  • Previous by thread: Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
  • Next by thread: Bug in CF/NSString's no-copy constructors (was Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful)
  • Index(es):
    • Date
    • Thread