Reputation: 1092
Not sure how correctly formulate the question but here is the problem.
I have a static lib where I have the following class in a.h:
#pragma once
#include <vector>
class A{
public:
void Run() {
data_.push_back(10);
std::cout << "size: " << data_.size() << std::endl;
}
private:
static std::vector<int> data_;
};
a.cpp is as follows:
#include "a.h"
std::vector<int> A::data_;
And I have another class in b.h:
#pragma once
#include <string>
class B
{
public:
static std::string Get();
};
And b.cpp:
#include "b.h"
#include "a.h"
std::string B::Get()
{
static A a;
a.Run();
return "foo";
}
Now my main app which is using the above static lib is as follows:
#include <iostream>
#include "a.h"
#include "b.h"
static std::string var1= B::Get();
int main(int argc, char** argv)
{
A a;
a.Run();
}
Trying to understand why the output is:
size: 1
size: 1
There should be a single instance of each static data member for the entire class, so there should be a single call to A::data_ constructor. Am I hitting "static initialization order fiasco"? I.e. data_ is not initialised before I use it, but then I should be getting the crash?
And now lets imagine my data_ holds dynamically initialised items (something none POD). How will it be destructed if at the end data_ holds one item, although I've inserted 2?
And that's what actually is happening in my real life code (it sometimes crashes during destruction of data_).
Getting rid of global static ( static std::string var1= B::Get(); ) solves the problem, but I still want to understand the under the hood problem.
The described case can be reproduced in VS2015 (the real life case is reproducible in gcc 6.2 )
Upvotes: 0
Views: 94
Reputation: 206577
Am I hitting "static initialization order fiasco"?
Most likely.
You can remove the problem by making the static
data of a class available via a function call. E.g.
class A{
public:
void Run() {
getData().push_back(10);
std::cout << "size: " << getData().size() << std::endl;
}
private:
static std::vector<int>& getData();
};
std::vector<int>& A::getData()
{
static std::vector<int> data;
return data;
}
When you do that, data
will be initialized when A::getData()
is called the first time. It removes the static initialization order issue completely.
Upvotes: 1