Quick context: I'm seeing errors on program shutdown, that stem from dependencies between global members (::sigh::, I know, I know). One global variable's destructor might refer to another global -- and if that one's already been destructed, things get bad.
But here's a particular case where I just don't know whether behavior is well-defined: a static variable inside a function. Can I rely on the function behaving consistently even during program shutdown? Or is it possible that the static member will be destroyed, and the function will run anyway, without creating a new one?
Here's a toy example demonstrating what I'm interested in:
class Logger
{
public:
enum class Severity { DEBUG, INFO, WARNING, ERROR };
void Log(Severity sev, const std::string& msg)
{
LogImpl(FormatMessage(sev, msg));
}
Logger() { Log(Severity::INFO, "Logger active"); }
~Logger() { Log(Severity::INFO, "Logger inactive"); }
protected:
static std::string FormatMessage(Severity sev, const std::string& msg)
{
static const std::map<Severity, std::string> enum2str {
{Severity::DEBUG, "DEBUG"},
{Severity::INFO, "INFO"},
{Severity::WARNING, "WARNING"},
{Severity::ERROR, "ERROR"}
};
// Throws or crashes if enum2str is invalid, or uninitialized:
return "[" + enum2str[sev] + "] " + msg;
}
void LogImpl(const std::string& msg)
{
std::cout << msg << std::endl;
}
};
Let's imagine I have a global instance of Logger. The enum2str map in Logger::FormatMessage is a static variable, so at some point during program shutdown, it will be destroyed.
By standard, can this cause my program to crash on shutdown? Is enum2str inherently unreliable during shutdown? Or is there some handling of this -- for example, if enum2str is invalid at some point, perhaps a new static instance will be created?
(I am not interested in relying on destruction order between objects, e.g. where I declare the global Logger instance.)