2

I faced a problem using a Boost variant. I have a segmentation fault when the variant gets destructed.

The weird thing is that this segmentation fault occurs only when I do not activate the optimizations of the compiler (GCC in my case). For example, in O1, O2, O3 mode, I have no problem running my code.

My variant is defined like that :

typedef boost::variant<
            ASTFunctionCall, 
            ASTSwap, 
            ASTDeclaration,
            ASTAssignment, 
            ASTIf,
            ASTWhile,
            ASTForeach,
            ASTFor>
        ASTInstruction;

All the elements of the variant are some Deferred. The Deferred construct enable the deferred construction of objects. That seems that the object is not constructed before there is an access to one of its fields. The real object is backed with a shared_ptr.

And the error occurs from the destruction of a parent :

struct FunctionDeclaration { 
    std::shared_ptr<FunctionContext> context;
    std::string returnType;
    std::string functionName;
    std::string mangledName;
    std::vector<FunctionParameter> parameters;
    std::vector<ASTInstruction> instructions;
};

When the vector of instructions gets deleted, the segmentation fault occurs when the delete of the variant occurs at this specific function :

0x0000000000d71972 in boost::variant < eddic::Deferred < eddic::FunctionCall, std::shared_ptr < eddic::FunctionCall > >, eddic::Deferred >, eddic::Deferred < eddic::Declaration, std::shared_ptr < eddic::Declaration> >, eddic::Deferred < eddic::Assignment, std::shared_ptr < eddic::Assignment > >, eddic::Deferred < eddic::If, std::shared_ptr < eddic::If > >, eddic::Deferred < eddic::While, std::shared_ptr < eddic::While> >, eddic::Deferred < eddic::Foreach, std::shared_ptr < eddic::Foreach> >, eddic::Deferred < eddic::For, std::shared_ptr < eddic::For> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::using_backup() const ()

EDIT 2 : After removing recursive_wrapper and intrusive_ptr to test, the error is now an assert of boost : Boost.Variant internal error: which out of range.

Is there some limitations on variant for destructions ? Like some kind of classes that we cannot put in a variant ?

Thanks in advance for any idea relating to this problem

EDIT : Can it comes from the fact that the variant contains several times a Deferred, Deferred, ... ?

madth3
  • 7,275
  • 12
  • 50
  • 74
Baptiste Wicht
  • 7,472
  • 7
  • 45
  • 110
  • My hunch is indeed that recursive_wrapper is less-well tested for tree-recursive variant types. You could check in the test suites whether it is part of the test coverage – sehe Nov 10 '11 at 13:15
  • recursive_wrapper was not in cause. Indeed, I removed it totally as Deferred is also giving me the possibility to use a type not completely defined (Deferred dynamically allocates the object). – Baptiste Wicht Nov 10 '11 at 21:33

1 Answers1

1

I don't know exactly what semantics you need, but could you simplify the variant structure tree like so:

typedef boost::variant<
        ASTFunctionCall, 
        ASTSwap, 
        ASTDeclaration,
        ASTAssignment, 
        boost::recursive_wrapper<
            boost::variant<ASTIf, ASTWhile, ASTForeach, ASTFor> >
    ASTInstruction;

?

sehe
  • 374,641
  • 47
  • 450
  • 633
  • What would be the advantage of such a structure ? If that can solve the problem, I will adopt it, but I will have to rewrite all my visitors. I just tried it but I have some conversion errors more than just visitors. – Baptiste Wicht Nov 10 '11 at 15:51
  • @BaptisteWicht: to be honest, I would consider it a bug workaround. Then again, I have never seen a '_multi-recursive_' variant before, so perhaps someone a lot more intelligent than me can explain whether that should be (im)possible and why – sehe Nov 10 '11 at 15:54
  • @BaptisteWicht: can you do an isolated check that the 'destructor' issue doesn't occur using this workaround? You could spare the effort if it doesn't change a thing. Also, if it **does 'fix' the destructor issue** I suggest posting at the [developer list for Boost](http://www.boost.org/community/groups.html) to get an educated bug opinion – sehe Nov 10 '11 at 15:59
  • I removed recursive_wrapper, so the problem was in that part. – Baptiste Wicht Nov 10 '11 at 21:34
  • @BaptisteWicht: i'm very interested in what became of it (how did you employ Deferred) and whether you feel it was a bug (worth reporting) – sehe Nov 10 '11 at 22:01
  • Sorry... My message is lacking a 'not' (getting tired) :( It didn't changed anything after removing recursive_wrappers – Baptiste Wicht Nov 10 '11 at 22:09
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/4894/discussion-between-sehe-and-baptiste-wicht) – sehe Nov 10 '11 at 22:15