I'm getting a segmentation fault and I don't know why, I had thought the variable is being initialised properly.
I want a class to provide access to a global configuration manager class, so I have the following factory class set out below. There is a means (via the setConfigurationManagerForTesting()
method) of injecting a different ConfigurationManager
class into the factory that will be returned in order to facilitate easier testing. It is not called by the code that has the failure.
/**
* @brief Factory class that creates a global instance of ConfigurationManager
*/
class ConfigurationManagerFactory {
public:
/**
* @brief Get the global ConfigurationManager
* @return The global ConfigurationManager
*/
static ConfigurationManager &getConfigurationManager();
/**
* @brief Set the ConfigurationManager to a defined instance, to allow for testing
*
* @param configurationManager The ConfigurationManager that should replace the default one
*/
static void setConfigurationManagerForTesting(ConfigurationManager *configurationManager);
// commented out to allow for trying to track down the failure
// private:
ConfigurationManagerFactory() {}
static ConfigurationManager configurationManager;
static ConfigurationManager *configurationManagerPtr;
};
Here is the implementation in the .cpp
file:
ConfigurationManager ConfigurationManagerFactory::configurationManager;
ConfigurationManager *ConfigurationManagerFactory::configurationManagerPtr = nullptr;
ConfigurationManager &ConfigurationManagerFactory::getConfigurationManager() {
if (configurationManagerPtr == nullptr) {
configurationManagerPtr = &configurationManager;
}
return *configurationManagerPtr;
}
void ConfigurationManagerFactory::setConfigurationManagerForTesting(ConfigurationManager *testingConfigurationManager) {
configurationManagerPtr = testingConfigurationManager;
}
The initialisation of the static member variables is as per that set out in this SO question.
The failing code within a Google test:
std::cout << "ok so far 1" << std::endl;
ConfigurationManager &cm = ConfigurationManagerFactory::getConfigurationManager();
std::cout << "ok so far 2" << std::endl;
ASSERT_EQ(&cm, ConfigurationManagerFactory::configurationManagerPtr);
std::cout << "ok so far 3" << std::endl;
cm.getConfiguration();
std::cout << "ok so far 4" << std::endl;
Output:
ok so far 1
ok so far 2
ok so far 3
:test FAILED
The test fails with exit code 139, which is a segmentation fault. I can't check (don't know how to check) that the address to which the configurationManagerPtr
variable points is valid, but the assertion shows that it points at the static member variable.
The getConfiguration()
method where the failure occurs simply returns (by value) a member variable of the ConfigurationManager
:
class ConfigurationManager {
public:
ConfigurationManager();
virtual ~ConfigurationManager() {}
virtual boost::property_tree::ptree getConfiguration();
protected:
boost::property_tree::ptree configuration;
};
boost::property_tree::ptree ConfigurationManager::getConfiguration() {
return configuration;
}