встроенная переменная инициализируется более одного раза - PullRequest
0 голосов
/ 07 ноября 2018

Я вижу несколько примеров того, как переменная inline const инициализируется (и уничтожается) 3 раза в Visual Studio 2017. Это ошибка компоновщика? или это должно произойти как-то иначе?

компоновщик Comdat для фальцовки выключен.

Пример кода:

#pragma once

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


inline const A a = A();

В моем решении у меня есть огонь подтверждения дважды (конструктор вызывается 3 раза). Проверка стека вызовов показывает, что все стеки вызовов идентичны, и все вызовы поступают из динамического инициализатора для (). Теперь я точно знаю, что этот класс не используется в других частях решения, поскольку я просто создал его, чтобы исследовать эту проблему.

Я использую VS17 15.8.9

Обновление: отчет об ошибках здесь https://developercommunity.visualstudio.com/content/problem/297876/static-inline-variable-gets-destroyed-multiple-tim.html (вы можете проголосовать, чтобы помочь исправить ошибку)

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

Я получаю ошибку в режиме отладки и выпуска (/ Ox) с использованием компилятора MS C ++ версии 19.16 (поставляется, например, с 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"    

После компиляции и компоновки inline.cpp и inline2.cpp вывод при запуске:

Constructing a Foo at 00BE4028  
Constructing a Foo at 00BE4028  

Компилятор и компоновщик правильно разрешают два встроенных определения в один объект, но некорректно вызывают конструктор для каждого определения, а не один раз. Это серьезная ошибка, которая делает функцию «встроенной переменной» C ++ 17 непригодной для использования. «Обходной путь» - рассматривать встроенные переменные как все еще не поддерживаемые MS C ++ начиная с версии 19.16, даже когда используется ключ / std: c ++ 17.

0 голосов
/ 07 ноября 2018

Это похоже на ошибку MSVC. Я могу воспроизвести его с кодом ниже (также с VS2017 15.8.9). Интересно, что я могу воспроизводить только с помощью сборки Debug. В режиме Release оптимизатор, кажется, спасает нас.

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();
}

Вывод (отладка)

Constructing a Foo
Constructing a Foo
00007FF74FD50170
00007FF74FD50170
Destructing a Foo
Destructing a Foo
...