c++ - Template member functions, static local variables and destruction order -
first of all, sorry english:
i've designed little library manage memory program uses. implements kind of shared object memory management purposes. have following classes (i omit other members , functions don't need here explain problem):
- a parametric struct called
packet
contains subobject of typet
, counter:
template<class t> struct packet { t t; unsigned counter; };
- a parametric class called
ptrstack
:stack
destructor callsdelete
each pointer stack contains, when destructor called:
template<typename t> struct ptrstack : public std::stack<t*> { ~ptrstack() { while(!this->empty()) { delete this->top(); this->pop(); } } };
- a class called
pool
static parametric function (and other code, of course) returning referenceptrstack
:
class pool { template<class t> using stack_tp = ptrstack<packet<t> >; public: template<class t> static stack_tp<t>& get() { static stack_tp<t> pool; return pool; } };
- finally, parametric class
shared_obj
template<typename t> class shared_obj { /* members (see below) */ };
- user classes inherit
shared_obj
:
struct internals_t; // definition in .cpp source code (pimpl idiom). // `shared_obj` uses pointer type parameter. class user_t : public shared_obj<internals_t> { // member functions accessing internal pointer. // `user_t` light. mantains pointer, used // common object. // moreover, can work dynamic objects without using new , delete // since memory managed shared_obj };
construction, assignment/copies , destruction perform fundamentally following actions:
- each time new
shared_obj<t>
wanted created,packet<t>*
created in heap. - each time
shared_obj<t>
copied, counter of associated packet incremented. - each time destructor of
shared_obj<t>
called, counter of associated packet decremented. - if counter of associated packet reachs 0, associated pointer pushed on stack means of:
pool::get<t>().push(ptr);
- so, redefine first point of list: when new
packet<t>*
wanted created, , pool of type empty, new packet created in heap. if pool isn't empty, use "in-place" version of new:
new (pool::get<t>().top()) t(args); pool::get<t>().pop();
so, destruction delegated when program exits, , created memory reused.
enough explanations!!
my problem is: need other statics objects of type "user_t
" (really, different object of different types inheriting shared_obj
), of them produce memory leaks, , thing following reason:
- that static objects being created before creation of associated pools, because of definition of
packet_pool.get<t>()
each type instantiated after definition: template definitions instantiated concrete type in first pointer of use , not template written. so, lexical order in files different definition order in translated unit. - in consequence, static objects being destructed after associated pools, because static objects deleted in inverse order of construction, , coincides definition order of translated unit.
- when static objects destructed, associated counter reachs 0 , try pushed in destructed pool. throws crash.
my doubt following:
- what concrete "definition order" instantiated template functions in translation unit? assumptions correct?
and here parallel question:
- can problem related fact pool local static function or "get" function inlined (because it's function defined inside class)? mean, each "pool" (each stack) have internal linkage , have different
pools
same type in different translation units?
Comments
Post a Comment