Hi guys,
Have been messing with this for a few days now, and now, even though I'm stripping all the code I can, it doesn't seem to change behaviour.
I'm talking about a Segfault that occurs when i try to insert a pair (or anything, really) into a static map, in my constructor.
SceneElement.h :
#ifndef SCENEELEMENT_H
#define SCENEELEMENT_H
#include <string>
#include <vector>
#include <map>
namespace world
{
class SceneElement
{
protected:
const std::string name;
const unsigned ssid;
static unsigned element_ssid_tail;
public:
static std::map< unsigned, SceneElement* > element_ssid_table;
static std::map< std::string, SceneElement* > element_name_table;
SceneElement(const std::string &_name = "Unnamed element", const bool _visible = true);
SceneElement(const SceneElement& orig);
virtual ~SceneElement();
};
}
#endif /* SCENEELEMENT_H */
SceneElement.cpp :
#include "SceneElement.h"
#include <iostream>
namespace world
{
unsigned SceneElement::element_ssid_tail = 1; // 0 is an invalid subsystem id
std::map< unsigned, SceneElement* > SceneElement::element_ssid_table = std::map< unsigned, SceneElement* >();
std::map< std::string, SceneElement* > SceneElement::element_name_table = std::map< std::string, SceneElement* >();
SceneElement :: SceneElement(const std::string &_name, const bool _visible) :
ssid(SceneElement::element_ssid_tail),
name(_name)
{
++SceneElement::element_ssid_tail;
std::cout << this << std::endl; // Outputs reasonable address
std::cout << &SceneElement::element_ssid_table << std::endl; // Outputs reasonable address
std::cout << &SceneElement::element_name_table << std::endl; // Outputs reasonable address (located a few bytes after the previous map)
std::cout << SceneElement::element_ssid_table.size() << std::endl; // Outputs 0
std::cout << SceneElement::element_ssid_tail << std::endl; // Outputs 2
// Setting the maps here makes everything work. I'd guess that the static map hasn't been initialized properly....
//SceneElement::element_ssid_table = std::map< unsigned, SceneElement* >();
//SceneElement::element_name_table = std::map< std::string, SceneElement* >();
// Crashes!
SceneElement::element_ssid_table.insert( std::pair< unsigned, SceneElement* >(ssid, this) );
SceneElement::element_name_table.insert( std::pair< std::string, SceneElement* >(name, this) );
}
SceneElement :: SceneElement(const SceneElement& orig) :
ssid(SceneElement::element_ssid_tail),
name(orig.name)
{
++SceneElement::element_ssid_tail;
// Crashes!
SceneElement::element_ssid_table.insert( std::pair< unsigned, SceneElement* >(ssid, this) );
SceneElement::element_name_table.insert( std::pair< std::string, SceneElement* >(name, this) );
}
SceneElement::~SceneElement()
{
SceneElement::element_ssid_table[ssid] = NULL;
SceneElement::element_name_table[name] = NULL;
}
}
The punchline here is, that I've got a GuiElement class that behaves that exact same way, but never crashes.
And I'm not fond of undefined behaviour, so if I'm just being lucky with GuiElement, then I'd rather change it to a "safe" implementation.
I felt confident that everything static, that had been included, compiled and linked would be initialized first thing,
and it looks like the maps have actually been created. Would you give me a hand?
Tips on preventing segfaults are also welcome. I usually create on construction or on the stack, avoid "new" where possible,
and deal in refs instead of pointers, when possible. But this apparently, I have not been able to escape.