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;
}
Static variables are initialized only once. Compiler persist the variable till the end of the program. Static variable can be defined inside or outside the function.
A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.
A static method or variable doesn't require an instance of the class in order to run. Before an object of a class is created, all static member variables in a class are initialized, and all static initialization code blocks are executed.
The space for the static variable is allocated only one time and this is used for the entirety of the program. Once this variable is declared, it exists till the program executes. So, the lifetime of a static variable is the lifetime of the program.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With