I am confused by the result i am getting from this code. In one dll the counter is incremented when the static variable is initialized. Then when main is executed i read this counter but i get 0 instead of 1. Can anybody explain this to me?
In my dynamic library project:
// Header file
class Foo {
int i_ = 0;
Foo(const Foo&) = delete;
Foo& operator= (Foo) = delete;
Foo()
{
}
public:
void inc()
{
++i_;
}
int geti()
{
return i_;
}
static Foo& get()
{
static Foo instance_;
return instance_;
}
Foo( Foo&&) = default;
Foo& operator= (Foo&&) = default;
};
int initialize()
{
Foo::get().inc();
return 10;
}
class Bar
{
static int b_;
};
// cpp file
#include "ClassLocalStatic.h"
int Bar::b_ = initialize();
In my application project
// main.cpp
#include <iostream>
#include "ClassLocalstatic.h"
int main(int argc, const char * argv[])
{
std::cout << Foo::get().geti();
return 0;
}
The executable and DLL are both going to get their own copy of
Foo::get(), each with their own copy of the static variable. Because they’re in separate linker outputs, the linker can’t consolidate them as it would normally.To expand on this further:
The C++ specification allows an inline function to be defined in multiple translation units as long as they all have the same body; putting the function in a header file is perfectly OK because it ensures each copy will be identical. See https://stackoverflow.com/a/4193698/5987 . If there are static variables within the inline function, the compiler and linker need to work together to make sure that only one copy gets used between all of them. I’m not sure of the exact mechanics but it does not matter, the standard requires it. Unfortunately the reach of the linker stops after it has produced the output executable or DLL and it is unable to tell that the function exists in both places.
The fix is to move the body of
Foo::get()out of the header and put it in a source file that’s only in the DLL.