------- Comment #2 from varg at theor dot jinr dot ru 2008-03-13 06:42 ------- Richard Guenther wrote:
> the object compare is invoked on is not properly initialized (its _vptr is > NULL). Not exactly. The object (or rather, the pointer managed by that objects) gets deleted too early. > Please try to simplify the test program. template <class T> class ptr { T* p; public: ptr(T* t) throw() : p(t) { p->set_refcount(1); } explicit ptr(T& t) throw() : p(&t) { p->add_reference(); } ptr(const ptr& other) throw() : p(other.p) { p->add_reference(); } ~ptr() { if (p->remove_reference() == 0) delete p; } ptr& operator=(const ptr& other) { T* otherp = other.p; otherp->add_reference(); if (p->remove_reference() == 0) delete p; p = otherp; return *this; } T& operator*() const throw() { return *p; } T* operator->() const throw() { return p; } }; class refcounted { public: refcounted() throw() : refcount(0) { } unsigned add_reference() throw() { return ++refcount; } unsigned remove_reference() throw() { return --refcount; } unsigned get_refcount() const throw() { return refcount; } void set_refcount(unsigned r) throw() { refcount = r; } private: unsigned refcount; }; class ex; enum status_flags { dynallocated = 1, evaluated = 2 }; class basic : public refcounted { public: basic() : flags(0) { } basic(const basic& other) : flags(other.flags & ~dynallocated) { } virtual basic* duplicate() const { return new basic(*this); } virtual ex eval() const; const basic& hold() const { flags |= evaluated; return *this; } virtual ~basic() { } protected: mutable unsigned flags; private: friend class ex; }; class ex { private: mutable ptr<basic> bp; static ptr<basic> construct_from_basic(const basic& other) { if (!(other.flags & evaluated)) { const ex& tmpex = other.eval(); if ((other.get_refcount() == 0) && (other.flags & dynallocated)) delete &other; return tmpex.bp; } else { if (other.flags & dynallocated) { return ptr<basic>(const_cast<basic &>(other)); } else { basic* bp = other.duplicate(); bp->flags |= dynallocated; return bp; } } } public: ex(const basic& other) : bp(construct_from_basic(other)) { } ex eval() const { return bp->eval(); } }; ex basic::eval() const { return hold(); } class oops : public basic { public: oops() { } oops* duplicate() const { return new oops(*this); } ex eval() const { return oops().hold(); } }; int main(int argc, char** argv) { const ex e = oops().hold(); const ex& f = argc > 1 ? e : e.eval(); const ex& g = f.eval(); return 0; } -- varg at theor dot jinr dot ru changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |varg at theor dot jinr dot | |ru http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35548