On Sun, May 10, 2015 at 5:30 AM, Nick Wellnhofer <[email protected]> wrote:
> On 09/05/2015 18:58, rectang wrote:
>>
>> Conspicuous omissions include Obj and Err which need to be
>> extensible, and String and StringIterator, which need to be refactored to
>> accommodate stack allocations without subclassing.
>
> I created a branch that eliminates StackStrings as a separate class:
>
> https://github.com/nwellnhof/lucy-clownfish/commits/stack_objects
This branch is great -- especially the generalization of stack allocation to
extend to types beyond String. It would be great if Clownfish eventually
arrives at a coherent model for object lifetime management that is flexible
enough to work with any host and stable enough to be published as an API.
There is one thing missing from this branch. Clownfish separates the phase of
object allocation from the phase of class initialization; the class
initializer must be presented with a memory block which meets the following
criteria:
* Host-specific allocation initialization complete.
* Clownfish Class pointer member var set.
* Allocation primed to take part in automatic memory management scheme,
either through registry with GC or by initializing refcount to 1.
* All member variables set to zero values.
What is missing from `CFISH_ALLOCA_OBJ` routine is zeroing of memory --
because memory returned by `alloca` is not guaranteed to be zeroed.
There are two reasons that memory supplied to a class initializer needs to be
zeroed. First, class initializers may be relying on it for fields with a
default zero value.
Second, it is possible for object destruction to commence before class
initialization finishes, for example if some intermediate routine throws an
exception or returns an invalid value. If this happens, and a pointer
member variable is set to a garbage value, then dereferencing that pointer
during destruction will cause a memory error.
Foo_do_open(Foo *self, ThingFactory *factory) {
Thing *thing = ThingFactory_Make_Thing(factory);
if (!thing) {
DECREF(self);
return NULL;
}
foo->thing = thing;
return self;
}
Foo_destroy(Foo *self) {
DECREF(foo->thing); // <-- mem error if `thing` is invalid
SUPER_DESTROY(self, FOO);
}
I suggest that the proper place for the memory zeroing is inside
Class_Init_Obj.
+1 to merge the branch, so long as we either add a commit fixing this issue or
open a ticket.
Marvin Humphrey