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.