Я работаю над нетривиальным синтаксическим анализатором в C ++ поверх boost :: spirit :: x3. Я делю свой код разбора на логические единицы, некоторые из которых являются зависимостями друг от друга. Например, одна единица является анализатором выражений, который также предоставляет синтаксический анализатор идентификатора. Многие высокоуровневые конструкции syntacti c целевого языка включают выражения и идентификаторы, поэтому этот модуль часто является зависимостью. Я разбил код на тройки файлов , как рекомендует документация . Если есть единицы foo , bar и quux , у меня есть файлы вроде:
parser
foo.h
foo_def.h
foo.cpp
bar.h
bar_def.h
bar.cpp
quux.h
quux_def.h
quux.cpp
, где .h
расширяется BOOST_SPIRIT_DECLARE
; _def.h
расширяется BOOST_SPIRIT_DEFINE
, а .cpp
расширяется BOOST_SPIRIT_INSTANTIATE
. Я столкнулся с постоянной проблемой, из-за которой мой код выдает ошибки при запуске из-за фиаско инициализации stati c в коде Spirit (строка 160 из ... / x3 / nonterminal / rule.hpp), но только при выполнении отладочной сборки.
Основываясь на вопросах и ответах stackoverflow, таких как этот и этот плюс тот факт, что код выполняется без ошибок при сборке в конфигурации выпуска, я считаю, что есть ничего плохого в моем коде. Я вижу два обходных пути, если нет способа исправить мой код в отладке:
Только в отладочных сборках используйте объявление прагмы, чтобы изменить порядок инициализации stati c. (Изменение порядка элементов в файле .vcxproj не повлияло на порядок инициализации) В Visual Studio, если я добавлю #pragma init_seg(lib)
в файл. cpp моего анализатора выражений, проблема исчезнет.
Только в отладочных сборках при необходимости включайте лишние _def.h
файлы, например, если quux зависит от bar выше, то включение bar_def.h
в quux.cpp
исправит проблема, но побеждает цель разбить анализатор на несколько файлов.
Мне вообще интересно, каково состояние этой проблемы? Кажется, это известная проблема, но она существует уже давно, и поэтому я не должен ожидать, что она будет исправлена на уровне Духа? Есть ли лучший способ структурировать мой код так, чтобы эта проблема не возникала? Мне было интересно, возможно ли, например, создать все парсеры и их дочерние парсеры как переменные stati c в области действия функции, создаваемой при первом использовании, но в литературе нет примеров, подобных этому, поэтому я не уверен, что это так. возможный?