inline variable is initialized more than once
This appears to be an MSVC bug. I'm able to reproduce it with the code below (also with VS2017 15.8.9). Interestingly, I can only reproduce with a Debug build. In Release mode, the optimizer seems to save us.
Common.h
#pragma once
#include <iostream>
class Foo
{
public:
Foo()
{
std::cout << "Constructing a Foo" << std::endl;
}
~Foo()
{
std::cout << "Destructing a Foo" << std::endl;
}
};
inline Foo const Bar;
other.cpp
#include "common.h"
void DoOtherStuff()
{
std::cout << &Bar << std::endl;
}
main.cpp
#include "common.h"
void DoStuff()
{
std::cout << &Bar << std::endl;
}
extern void DoOtherStuff();
int main()
{
DoStuff();
DoOtherStuff();
}
Output (Debug)
Constructing a Foo
Constructing a Foo
00007FF74FD50170
00007FF74FD50170
Destructing a Foo
Destructing a Foo
I get the bug in both debug and release (/Ox) mode using the MS C++ compiler version 19.16 (comes with, e.g., Visual Studio 15.9.4).
Inline.Hpp
#include <iostream>
inline struct Foo
{ Foo() { std::cout << "Constructing a Foo at " << this << std::endl; } }
Instance;
Inline.cpp
#include "Inline.Hpp"
int main() { return 0; }
Inline2.cpp
#include "Inline.Hpp"
After compiling and linking inline.cpp and inline2.cpp, the output on running is:
Constructing a Foo at 00BE4028
Constructing a Foo at 00BE4028
The compiler and linker correctly resolve the two inline definitions to a single object, but incorrectly call the constructor for each definition, instead of just once. This is a serious bug which renders the "inline variable" feature of C++17 unusable. The "workaround" is to regard inline variables as still unsupported by MS C++ as of version 19.16, even when the /std:c++17 switch is used.
As of today there is an update for visual studio 2017 to version 15.9.24 which fixes the problem.
From the release notes:
Fixed C++ compiler bug for proper folding of inline variable dynamic initializers.