Нелегко определить, в чем заключается мой вопрос программирования, так как я не понимаю, в чем проблема. Действительно, у меня есть ошибка во время выполнения, потерянная где-то в Библиотеке кармы бодрости духа. Я полагаю, что мне здесь не хватает техники отладки.
Я видел, что макрос BOOST_SPIRIT_DEBUG_NODE (S), очень помогает парсерам, хотя я не нашел ссылки на него в руководстве. Для генераторов, кажется, это не работает, и у меня (честно) не хватает смелости (я должен?) Копаться в коде этой библиотеки, чтобы понять, где проблема.
Я попытался сгенерировать три типа моей единой структуры в грамматике без каких-либо проблем. Таким образом, я предполагаю, что ошибка происходит из преобразования структуры U в вариант наддува, снова (см. Приведение атрибута для повышения :: вариант) но у меня нет доказательств.
Для тех, кто может решить эту проблему с помощью простой проверки кода, вот минимальный пример моей проблемы:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/karma.hpp>
#include <boost/variant/variant.hpp>
namespace ka = boost::spirit::karma;
typedef std::back_insert_iterator<std::string> iterator;
typedef enum {A, B, C } E;
typedef enum {FOO, BAR, POINTER } K;
struct U /* Union like */
{
K kind;
double foo;
E bar;
unsigned int * p;
};
class EName : public ka::symbols<E, std::string>
{
public:
EName()
{
add (A,"A") (B,"B") (C,"C");
}
};
typedef boost::variant<E, double, unsigned int *> UVariant;
namespace boost { namespace spirit { namespace traits {
template<>
struct transform_attribute<const U,UVariant,ka::domain>
{
typedef UVariant type;
static type pre(const U & u) {
switch (u.kind)
{
case FOO:
return type(u.foo);
case BAR:
return type(u.bar);
case POINTER:
return type(u.p);
}
return type(A);
}
};
}}}
class grm: public ka::grammar<iterator, U()>
{
public:
grm():grm::base_type(start)
{
start = ka::attr_cast<UVariant >(bar | foo | pointer);
bar = b;
foo = ka::double_;
pointer = ka::hex;
}
private:
ka::rule<iterator,U()> start;
ka::rule<iterator,double()> foo;
ka::rule<iterator,E()> bar;
ka::rule<iterator,unsigned int *()> pointer;
EName b;
};
int main(int argc, char * argv[])
{
grm g;
U u;
//unsigned int a;
u.kind = BAR;
//u.foo = 1.0;
u.bar = B;
//u.p = &a;
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
ka::generate(sink,g,u);
std::cout << generated;
return 0;
}
ОБНОВИТЬ: Компилятор: Visual C ++ Express версии 11 и 12. Стек вызовов останавливается на:
// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.
if (f(sink, context, delim)) // <--- call stack stops here (last boost spirit reference)
Также я узнал, что определение _SCL_SECURE_NO_WARNINGS макрос скрывает следующее предупреждение компилятора:
предупреждение C4996: ‘std :: _ Copy_impl’: вызов функции с параметрами, которые
может быть небезопасным — этот вызов полагается на вызывающего абонента, чтобы проверить, что
переданные значения верны. Чтобы отключить это предупреждение, используйте
-D_SCL_SECURE_NO_WARNINGS. См. Документацию о том, как использовать Visual C ++ «Проверенные итераторы».
Это предупреждение относится к нескольким файлам boost-spirit:
Я не могу воспроизвести ошибку.
Я не могу «решить» это из небольшой проверки кода. я Можно однако сделайте две вещи:
Я могу подтвердить, что макросы отладки не реализованы для Karma
Я могу выйти на конечности и сказать, что, возможно, bar|foo|pointer
должен быть глубоко скопирован:
start = ka::attr_cast<UVariant >(boost::proto::deep_copy(bar | foo | pointer));
Я пробовал с включенным UB-sanitizer и Address-sanitizer, но они оба не сообщали о каких-либо проблемах.
ОБНОВИТЬ На самом деле это выглядит как я Можно «решить» это из небольшой проверки кода (и счастливого мозгового волнения) в конце концов:
На самом деле, работает под Valgrind показывает проблема и действительно, он уходит при добавлении deep_copy
,
Я добавлю несколько ссылок на то, как я выдвинул гипотезу этих вещей:
в общем: проблема с висячими ссылками на временные шаблоны в (Proto) выражениях
в частности, проблема, замеченная несколько лет назад в qi::attr_cast<>
:
Других решений пока нет …