views:

142

answers:

1

I have a boost variant with 7 types in it. When I try to use the last two types, the linker segfaults. I am using g++ (gcc version 3.3.3 on SuSE Linux) on a 64 bit linux machine and the error that I get is

collect2: ld terminated with signal 11 [Segmentation fault]

It doesnt matter what order I put the types in, the last two will cause a segfault when I try to use them. Any ideas why this would be happening?

Code:

typedef boost::tuple<std::string, Class1::Ptr> Class1Tuple;
typedef boost::tuple<std::string, Class2::Ptr> Class2Tuple;
typedef boost::tuple<std::string, Class3::Ptr> Class3Tuple;
typedef boost::tuple<std::string, Class4::Ptr> Class4Tuple;
typedef boost::tuple<std::string, Class5::Ptr> Class5Tuple;
typedef boost::tuple<std::string, Class6::Ptr> Class6Tuple;
typedef boost::tuple<std::string, Class7::Ptr> Class7Tuple;

typedef boost::variant< Class1Tuple, Class2Tuple, Class3Tuple,
                        Class4Tuple, Class5Tuple, Class6Tuple,
                        Class7Tuple > ClassTupleItem;

ClassX::Ptr is a boost shared pointer to that class. Ptr is defined as a typedef inside the class itself as below

struct Class1
{
 typedef boost::shared_ptr<Class1> Ptr;
    ...
    ...
}

when I try to use the last two types in the boost variant as in

Class1Tuple tup("str", pointer);
ClassTupleItem(tup); // works fine since I used Class1Tuple

Class6Tuple tup2("str", pointer2);
ClassTupleItem(tup2); // causes a segfault.

if I define the boost::variant as (interchange Class6 and Class1)

typedef boost::variant< Class6Tuple, Class2Tuple, Class3Tuple,
                        Class4Tuple, Class5Tuple, Class1Tuple,
                        Class7Tuple > ClassTupleItem;

then I get a segfault when compiling this code

Class1Tuple tup("str", pointer);
ClassTupleItem(tup); // worked earlier
A: 

It looks like a compiler/linker bug: no C++ code should ever cause segfaults in the compiler/linker.

By the way, how do you get this code to compile? How is pointer declared?

Class1Tuple tup("str", pointer);
ClassTupleItem(tup); // works fine since I used Class1Tuple

Class6Tuple tup2("str", pointer);
ClassTupleItem(tup2); // causes a segfault.

If the classes are declared like this, for Class1Tuple, pointer should be a shared_ptr<Class1>, and for Class6Tuple it should be of a different type, shared_ptr<Class6>.

struct Class1
{
    typedef boost::shared_ptr<Class1> Ptr;
    /* ... */
};

/* ... */

struct Class6
{
    typedef boost::shared_ptr<Class6> Ptr;
    /* ... */
};

Edit: The following code compiles correctly with g++ 3.3.6. I am not able to test it on gcc 3.3.3 and SUSE Linux at the moment. Please try to compile this and see if the linker still gives a segfault.

#include <boost/shared_ptr.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/variant.hpp>
#include <string>

struct Class1
{
    typedef boost::shared_ptr<Class1> Ptr;
    /* .... */
};

struct Class2
{
    typedef boost::shared_ptr<Class2> Ptr;
    /* .... */
};

struct Class3
{
    typedef boost::shared_ptr<Class3> Ptr;
    /* .... */
};

struct Class4
{
    typedef boost::shared_ptr<Class4> Ptr;
    /* .... */
};

struct Class5
{
    typedef boost::shared_ptr<Class5> Ptr;
    /* .... */
};

struct Class6
{
    typedef boost::shared_ptr<Class6> Ptr;
    /* .... */
};

struct Class7
{
    typedef boost::shared_ptr<Class7> Ptr;
    /* .... */
};

typedef boost::tuple<std::string, Class1::Ptr> Class1Tuple;
typedef boost::tuple<std::string, Class2::Ptr> Class2Tuple;
typedef boost::tuple<std::string, Class3::Ptr> Class3Tuple;
typedef boost::tuple<std::string, Class4::Ptr> Class4Tuple;
typedef boost::tuple<std::string, Class5::Ptr> Class5Tuple;
typedef boost::tuple<std::string, Class6::Ptr> Class6Tuple;
typedef boost::tuple<std::string, Class7::Ptr> Class7Tuple;

typedef boost::variant< Class1Tuple, Class2Tuple, Class3Tuple,
                        Class4Tuple, Class5Tuple, Class6Tuple,
                        Class7Tuple > ClassTupleItem;

int main()
{
    Class1::Ptr pointer;
    Class1Tuple tup("str", pointer);
    (ClassTupleItem(tup)); // Temporary object
    ClassTupleItem item(tup);

    Class6::Ptr pointer2;
    Class6Tuple tup2("str", pointer2);
    (ClassTupleItem(tup2)); // Temporary object
    ClassTupleItem item2(tup2);
}
Danilo Piazzalunga
my pointers are declared exactly as you defined them.
TP
Then you shouldn't be able to costruct a `Class6Tuple` object with a `Class1::Ptr` when it expects a `Class6::Ptr`... unless an implicit conversion is taking place.
Danilo Piazzalunga
mistake in posting code. these two are defined in their own if blocks in the actual code and pointer for each is declared with its own class
TP
By the way, this code shouldn't compile (and it doesn't on gcc 3.3.6); the compiler sees the second line as a re-declaration of `tup`: `Class1Tuple tup("str", pointer); ClassTupleItem(tup);`
Danilo Piazzalunga