1

很难说出我的编程问题是什么,因为我真的不知道问题出在哪里。事实上,我在 boost 精神业力库的某个地方丢失了一个运行时错误。我想我在这里错过了一种调试技术。

我已经看到宏BOOST_SPIRIT_DEBUG_NODE(S)对解析器有很大帮助,尽管我在手册中找不到任何对它的引用。对于生成器,这似乎不起作用,我(老实说)没有勇气(我应该吗?)深入研究这个库的代码以了解问题出在哪里。

我试图在没有任何问题的情况下单独在语法中生成三种类型的联合结构。所以我假设错误来自将 U 结构转换为 boost 变体,再次(参见Casting attribute to boost::variant)但我没有证据。

对于那些可以通过简单的代码检查来解决它的人,这是我的问题的最小示例:

#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++ 'Checked Iterators' 的文档

此警告涉及几个 boost-spirit 文件:

  • spirit\home\karma\detail\output_iterator.hpp(242)
    spirit\home\karma\detail\output_iterator.hpp(577) 
    spirit\home\karma\detail\output_iterator.hpp(574) 
    spirit\home\karma\detail\ Alternative_function.hpp(170)
    spirit\home\karma\detail\alternative_function.hpp(162) 
    spirit\home\karma\operator\alternative.hpp(122)
    spirit\home\karma\auxiliary\attr_cast.hpp(85)
    spirit\ home\karma\nonterminal\detail\generator_binder.hpp(43)
    spirit\home\karma\nonterminal\detail\generator_binder.hpp(52)
    spirit\home\karma\nonterminal\rule.hpp(193)
    spirit\home\karma\非终端\rule.hpp(230)
4

1 回答 1

1

我无法重现错误。

我也无法通过一点代码检查来“解决它”。但是,我可以做两件事:

  • 我可以确认似乎没有为 Karma 实现调试宏

  • 我可以出去说也许bar|foo|pointer需要深度复制:

    start = ka::attr_cast<UVariant >(boost::proto::deep_copy(bar | foo | pointer));
    

我尝试启用 UB-sanitizer 和 Address-sanitizer,但它们都没有报告任何问题。


更新事实上,看起来我可以通过一点代码检查(和幸运的脑电波)“解决”它:

事实上,在 valgrind 下运行确实会出现问题,而且确实在添加deep_copy.

我将添加一些关于我如何假设这些事情的参考:

于 2016-07-11T20:46:28.910 回答