Why do Objective-C objects have to be dynamically allocated?
Asked Answered
I

3

17

Why do Objective-c objects have to be dynamically allocated? Why do I have to make it a pointer to an object, unlike in C++ I can create them on stack? Thanks.

Iatry answered 30/4, 2011 at 19:58 Comment(1)
Because Bjarne Stroustrup chose to implement copy/by value semantics whereas Brad Cox/NeXTSTEP/Apple chose not to.Sweetscented
E
17

the primary reason: not knowing how much stack size to reserve.

existing conventions and uses also make lifting the restriction quite difficult.

dynamic messaging does not matter in this case, as setting the right 'vtable' at initialization is trivial.

in c++, the size of a stack object is always known (and if it's wrong, you know what to expect). an objc alloc/init sequence can return any one of several types -- each with different sizes (it's essentially a factory), or nothing at all.

the size can also vary at runtime (e.g. you can add fields to a class via the runtime).

Update 1

i was curious about this, so i made a little test program as a proof of concept.

i was able to implement a simple stack based objc class hierarchy, which also implemented a good chunk of NSObject's interface -- of course, omitting the reference counting and dynamic allocation interfaces as it did not relate to the proof of concept. at any rate, my simple class hierarchy was not fully compatible with the NSObject class or protocol, so it isn't something that should be used where NSObject types are expected, for obvious reasons. therefore, it is possible (and not particularly difficult) to accomplish this, if you really wanted stack based objc objects.

you don't have to do anything different from c++ to reserve the stack space. the stack size to reserve is still a restriction in some areas (consider factory methods, class clusters, etc.).

there are also a few runtime functionalities which will not work by default. the best example here is the ability to add ivars at runtime. you could in fact accomodate this functionality, if you needed it. i didn't bother with that exercise.

naturally, the base interface could take several deviations - one deviation that i made for fun was adding the ability to exchange the implementations (type) of a living object.

have fun

Update 2

as it turns out, GCC accepts the proof of concept i wrote. unfortunately, this has been banned in clang due to problems/dangers which can be encountered in reserving the correct size (considering the dynamic features of the language...). example: clang forbids sizeof(NSObject). oh well.

Easting answered 30/4, 2011 at 20:41 Comment(10)
One disadvantage of stack objects is that there’s no concept of ownership — they’re necessarily destroyed at the end of the block/function/stack scope. This means that anything outside the stack scope needs to make copies of stack objects.Sweetscented
i prefer to call it another (automatic) ownership model. ownership is all well defined, it's just different from the dynamic model. in c++ programs that i write, locally created automatic objects are used most often (rather than allocations through an allocator), this is very important. when both models are available, and one needs to return an allocated object, the temporary you mention may be bypassed in most cases by creating the dynamic object when you know you will need it: return new MON::t_string(number);. for good and bad, c++ just has more.Easting
Another issue: Objective-C was originally implemented as a precompiler that generated C code. Passing objects by value is a problem in that case if the argument has a type different from the parameter type. It’s possible to cast pointers whereas casting structs isn’t even if they have the same initial layout.Sweetscented
if somebody were to implement this feature, then it would be best to pass by pointer or reference - but that's also the case in c++, because the stack objc object should still be assumed to be polymorphic (unless somebody wants to break a lot of existing programs in the process of implementing it). in any case, the object would still need the internal scaffolding for messaging. beyond that, the problem in c++ is called slicing. the remaining issues can be solved by using the interface (e.g. methods), rather than direct client access to ivars.Easting
btw, the model i have in mind assumes that such a model would involve constructors, destructors, copy semantics, and so on of c++, not c. for example, a compiler introduces default constructor, destructor, etc..Easting
In case you haven’t read it: Friday Q&A 2010-01-15: Stack and Heap Objects in Objective-C.Sweetscented
@Bavarious i had not read it. the proof of concept i wrote suggests that (some of) Mike's conclusions on the subject are short-sighted. i say "suggests" because it is merely a proof of concept, as opposed to long-lived, well tested, production level code. the POC demonstrates a simple objc class hierarchy, supporting all the usual stuff you want: subclassing, ivars, proper dynamic messaging, etc.. -- it's certainly further realized than Mike's struct { Class isa; } fakeNSObject; fakeNSObject.isa = [NSObject class];.Easting
update: gcc (+variants) accept the code, but clang rejects it: interface type cannot be statically allocatedEasting
I was able to get clang to create objects on the stack, using class_getInstanceSize(), alloca() and object_setClass(). That should get the dynamic size correct, too. Class clusters are still a problem. gist.github.com/iamleeg/5290797Masker
@GrahamLee that approach is similar to the implementation I wrote, though yours uses alloca which is safer than the approach used in my quick test. the problem then becomes object lifetime. since every instance is expected to be ref counted and shareable among multiple threads, its application is very limited. it also becomes more difficult to guarantee lifetimes in GC. afair, blocks are the only objc objects in the which are created on the stack, so it's completely abstracted at the source code level. i suppose there are a few other constructs which could use the stack (behind the scenes).Easting
S
2

Objective-c is a dynamic language, which means everything about it can change at runtime. The object's class object is only created when it is loaded from the executable, and it can be changed by categories. Also, the runtime can instance variables for properties. Since so much about the object can change after compilation, it cannot be created until it is used.

Stroke answered 30/4, 2011 at 20:7 Comment(0)
A
1

This is because of the way Objective-C uses dynamic or late binding. Unlike C++ where you'll always have the choice between calling a function of a class by it's object or via a pointer of the same class or even of a superclass. In the latter case polymorphism is required.

However, in Objective-C there exists always the ability to determine the correct function at runtime. The difference is, that for example in C++ the compiler has to ensure, that the used function exists, whereas in Objective-C the compiler doesn't really care, the runtime system decides only.

Apeldoorn answered 30/4, 2011 at 20:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.