1

問題がどこにあるのか実際にはわからないので、私のプログラミングの質問が何であるかを説明するのは簡単ではありません。確かに、ブースト スピリット カルマ ライブラリのどこかにランタイム エラーがありません。ここでデバッグ手法を見逃していると思います。

マクロBOOST_SPIRIT_DEBUG_NODE(S)がパーサーにとって非常に役立つことを確認しましたが、マニュアルには参照が見つかりませんでした。ジェネレーターの場合、これは機能していないようで、(正直なところ) このライブラリのコードを掘り下げて問題がどこにあるかを理解する勇気がありません (そうすべきでしょうか?)。

3 種類のユニオンのような構造を文法で単独で生成しようとしましたが、問題はありませんでした。したがって、エラーは U 構造体のブースト バリアントへのキャストに起因すると考えられます (「属性を 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' の使用方法に関するドキュメントを参照してください。

この警告は、いくつかのブーストスピリット ファイルを参照しています。

  • 精神\ホーム\カルマ\詳細\output_iterator.hpp(242)
    精神\ホーム\カルマ\詳細\output_iterator.hpp(577) 
    精神\ホーム\カルマ\詳細\output_iterator.hpp(574) 
    精神\ホーム\カルマ\詳細\ alternative_function.hpp(170)
    精神\ホーム\カルマ\詳細\alternative_function.hpp(162) 
    精神\ホーム\カルマ\オペレーター\alternative.hpp(122)
    精神\ホーム\カルマ\補助\attr_cast.hpp(85)
    精神\ホーム\カルマ\非ターミナル\詳細\generator_binder.hpp(43)
    精神\ホーム\カルマ\非ターミナル\詳細\generator_binder.hpp(52)
    精神\ホーム\カルマ\非ターミナル\rule.hpp(193)
    精神\ホーム\カルマ\非端末\rule.hpp(230)
4

1 に答える 1

1

エラーを再現できません。

少しのコード検査でも「解決」できません。ただし、次の2つのことができます。

  • デバッグ マクロが 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 に答える