From: David Kastrup Date: Sat, 4 Jun 2016 12:09:08 +0000 (+0200) Subject: Issue 4997/1: Add Preinit class for early initialization X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=0943e805fa82ebeb1d1ed32e675070467e340c39;p=lilypond.git Issue 4997/1: Add Preinit class for early initialization This is a tricky thing: once a base class calls smobify_self () in its constructor, further allocations during construction of base class and derived classes might lead to mark_smob calls on the object under construction. When those call a virtual function like derived_mark, the virtual function corresponding to the incompletely initialized object is likely to be called. This situation is acerbated in Guile 2.0 where the mark passes may occur with only loose synchronization to the allocations. The order of initialization of an object consists in calling the constructors of virtual base classes, then of non-virtual base classes, then initializing all data members. As a result, the derived constructor comes too late for initialization. That's where the Preinit template class comes in. Derive from it _before_ deriving from the smobifying base class providing derived_mark, and it will call its Base class' pre_init function (which must not rely on the instantiation being complete). The pre_init function should then put the derived class into a state _before_ its constructor or a constructor of its data members is being called where it's safe to call its derived_mark function. Note that in particular that most STL data structures are in undefined state before their constructor is being called, so the pre_init function has to establish a state where derived_mark will not attempt to interpret data members of types like std::vector which may not have been constructed yet. --- diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index 7ef46b23e4..0d446102e1 100644 --- a/lily/include/smobs.hh +++ b/lily/include/smobs.hh @@ -320,6 +320,32 @@ public: } }; +// This is a tricky thing: once a base class calls smobify_self () in +// its constructor, further allocations during construction of base +// class and derived classes might lead to mark_smob calls on the +// object under construction. When those call a virtual function like +// derived_mark, the virtual function corresponding to the +// incompletely initialized object is likely to be called. +// +// The order of initialization of an object consists in calling the +// constructors of virtual base classes, then of non-virtual base +// classes, then initializing all data members. +// +// As a result, the derived constructor comes too late for +// initialization. That's where the Preinit template class comes in. +// Derive from it _before_ deriving from the smobifying base class +// providing derived_mark, and it will call its Base class' pre_init +// function (which must not rely on the instantiation being complete). + +template +class Preinit { +protected: + Preinit () + { + (static_cast (this)) -> pre_init (); + } +}; + extern bool parsed_objects_should_be_dead; class parsed_dead {