Question

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, ... ?

Was it helpful?

Solution

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;

?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top