inline variable is initialized more than once

本小妞迷上赌 提交于 2019-12-17 16:47:19

问题


Im seeing some examples of inline const variable getting initialized (and destructed) 3 times with visual studio 2017. Is this is a bug with the linker ? or is this supposed to happend in some other way ?

linker Comdat folding is set to Off.

Example Code:

#pragma once

struct A {
  A() {
    static int count = 0;
    ++count;
    ASSERT(count == 1);
  }
  ~A() {
  }
};


inline const A a = A();

In my solution, I have the assert fire twice (A constructor called 3 times). Inspecting the call stack shows all call stacks are identical and all calls come from dynamic initializer for a(). Now I know for a fact this class is not used in other parts of the solution since I just created it to investigate this issue.

Im using VS17 15.8.9

Update: Bug report here https://developercommunity.visualstudio.com/content/problem/297876/static-inline-variable-gets-destroyed-multiple-tim.html (you may upvote to help push for the bugfix)


回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/53196700/inline-variable-is-initialized-more-than-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!