#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 удалось собрать его так, чтобы код работал нормально.