Orfby Orfby - 3 months ago 23
C++ Question

Accessing map inside union inside class gives segmentation fault

I am trying to create a class which either contains a map of one type or another, so I decided to use an anonymous union. But my code gives a segmentation fault when I try to access the map (in this case I get a segfault in both the constructor and the destructor):

#include <map>
#include <string>
#include <iostream>

class Foo
{
private:
union
{
std::map<std::string, int> ints;
std::map<std::string, std::string> strings;
};

bool fooContainsInts;

public:

Foo(bool containsInts) : fooContainsInts(containsInts)
{
if (containsInts) {ints = std::map<std::string, int>();}
else {strings = std::map<std::string, std::string>();}
}

~Foo()
{
if (fooContainsInts) {ints.clear();}
else {strings.clear();}
}
};

int main()
{
std::cout << "No segfault here!" << std::endl;
Foo foo(true);
std::cout << "This line doesn't get printed" << std::endl;
return 0;
}

Answer

I would suggest templating the type instead of a union, but maybe this helps you.

http://en.cppreference.com/w/cpp/language/union

The second example shows you how to deal with non-POD union members.

It should look like this

    Foo(bool containsInts) : fooContainsInts(containsInts) 
    {
        if (containsInts) { new (&ints) std::map<std::string, int>;}
        else { new (&strings) std::map<std::string, std::string>;}
    }

    ~Foo()
    {
        if (fooContainsInts) { ints.~map<std::string, int>(); }
        else { strings.~map<std::string, std::string>(); }
    }

I cant test it on MSCV though right now.

You need to explicitly construct and destruct non-POD union types