статическая локальная переменная во встроенной функции вызывает зависание в скомпилированном коде VS2015

#c #visual-studio-2013 #visual-studio-2015 #static #inline

#c #visual-studio-2013 #visual-studio-2015 #статический #встроенный

Вопрос:

У меня есть устаревший код в следующих строках:

 inline A::A() {
    static boost::shared_ptr<Data> data(new Data(""));
    data_ = data;
}
  

Data является некоторым классом и data_ нестатической переменной-членом class A . Я не уверен, какова была идея исходного кодера здесь, но интересно то, что этот код отлично работает при сборке с Visual Studio 2013, но когда он собран с Visual Studio 2015, код зависает (в строке, где инициализируется статическая переменная data ) во время DLLзагрузка.
Причина, по которой код вызывается во время загрузки DLL, заключается в том, что существуют статические объекты class A , например,

 class B
{
 static A a_;
}
  

Я понимаю, что VS2015 может создавать код по-другому, например, не соблюдая встроенную подсказку и т. Д. Но в чем причина его зависания? Это какое-то повреждение памяти?
Не пытаюсь заставить этот код работать — скорее пытаюсь понять потенциальную проблему, которую мог вызвать этот код.

Комментарии:

1. Я не уверен, что это выполнимо (минимальный, полный и проверяемый пример) — этот код является частью гигантского решения. Я пытаюсь понять теоретическую проблему, которая могла вызвать это, не обязательно для решения проблемы, которую пытается решить этот код. Возможно, что он не воспроизводится с какой-либо согласованностью.

2. Нам нужно увидеть контекст, в котором вызывается эта функция. Это также помогло бы узнать, что на самом Data деле делает конструктор. В опубликованном коде нет ничего, что дало бы нам представление о том, в чем проблема.

3. Трудно сказать наверняка, не видя остальной части кода, но похоже на фиаско статического порядка инициализации ( isocpp.org/wiki/faq/ctors#static-init-order )

4. Причина, по которой вызывается код, заключается в том, что в DLL есть куча статических объектов, которые используют класс A. Таким образом, предположение о том, что это фиаско статической инициализации, кажется вероятным.

5. @PeterD Вероятно, из-за некоторых деталей работы Data конструктора.

Ответ №1:

Спасибо Дэвиду Шварцу за предложение решения в комментариях к исходному вопросу. Проблема не была связана с каким-либо взаимодействием static локальной переменной и inline подсказки в конструкторе, как я предполагал. Вместо этого проблема заключалась в вызове конструктора Data , поскольку Data имеет переменную-член типа A . Это вызывает цикличность ( A , которая должна быть создана, нуждается Data , которая нуждается A ) Проблема решается с помощью идиомы именованного конструктора таким образом:

 class A{
  public:       
    static A createDefault()
    {
       static boost::shared_ptr<Data> data(new Data(""));
        A a;
        a.data_ = data;
        return a;
    }

  protected: 
    //Make the c'tor protected so that nobody uses it by mistake (except for derived classes) 
    A(){}

    //Struct Data can access A::A():
    struct Data{
       A a_;
       Data(string str) 
       {
           //...
       }
       //...
    };
};
  

Где-нибудь еще:

 //...
A a(A::createDefault());//or similar
//...
  

Остается загадкой, как VS2013 удалось собрать его так, чтобы код работал нормально.