1

これは、問題を再現するための最小限のコードです。唯一の外部前提条件は pugixml.hpp ファイルです。

コンテキストは、XML ファイル内の ID 参照を解決するためのクラスです (つまり、文字列値が与えられた場合、id 属性がその値に設定されているノードを見つけます)。pugixml API をラップするヘルパー クラスがいくつかあります。関連する部分は次のとおりです。

Agent.h

#include "pugixml.hpp"
#include <algorithm>
#include <functional>

    /**
     * Adapter to strip away the xpath layer around a xml_node.
     */
    template <typename Functor>
    struct Shim
    {
        Functor&    functor_;

        Shim( Functor&  functor ) 
        : functor_(functor) 
        {}

        void operator() ( pugi::xpath_node const& xpnode ) 
        {
            functor_( xpnode.node() );
        }
    };

    class Agent
    {
    public:
        explicit
        Agent( std::string const& xpath )
        : xpath_(xpath)
        {}

        // generic traverse over an xpath node_set
        template <typename Handler >
        size_t map( pugi::xml_node const& root, Handler& handler ) const
        {
            pugi::xpath_node_set    _xpset(root.select_nodes( xpath_.c_str() ));
            if ( _xpset.size() > 0 )
            {
                std::for_each( _xpset.begin(), _xpset.end(), Shim<Handler>(handler) );
            }
            return _xpset.size();
        }

    private:
        std::string     xpath_; // TODO: compile this into xpath_query?
    };

#define XML_Node    pugi::xml_node

IDリゾルバークラスの私の最初の実装はこれでした

IdNodeSet-ああ

#include "Agent.h"
#include <map>

    class IdNodeSet
    {
        typedef std::map<char const*, XML_Node> NodeMap;
    public: 
        IdNodeSet( XML_Node const& docRoot, XML_Node& defaultNode = XML_Node() )
        : map_()
        , default_(defaultNode)
        {
            Agent("//*[@id]").map( docRoot, *this );
        }

        void operator() ( XML_Node const& node )
        {
            map_[node.attribute("id").as_string()] = node;
        }

        XML_Node operator [] ( const char* id ) const
        {
            NodeMap::const_iterator _cit(map_.find( id ));
            return _cit != map_.end() ? _cit->second : default_;    
        }

    private:            
        NodeMap     map_;
        XML_Node    default_;
    };

これにより、Cygwin g++ 3.4.4 で次のエラーが発生しました (cygming スペシャル、gdc 0.12、dmd 0.125 を使用):

IdNodeSet-A.h:29: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://cygwin.com/problems.html> for instructions.

これは完全に不可解です。

私に起こる唯一のことは、コンストラクターで「* this」を使用することです。ただし、代わりにヘルパー メンバー クラスを使用した変更:

IDNodeSet-Bh

#include "Agent.h"
#include <map>

    class IdNodeSet
    {
        typedef std::map<char const*, XML_Node> NodeMap;
    public: 
        IdNodeSet( XML_Node const& docRoot, XML_Node& defaultNode = XML_Node() )
        : map_()
        , helper_(map_)
        , default_(defaultNode)
        {
            Agent("//*[@id]").map( docRoot, helper_ );
        }

        XML_Node operator [] ( const char* id ) const
        {
            NodeMap::const_iterator _cit(map_.find( id ));
            return _cit != map_.end() ? _cit->second : default_;    
        }

    private:            
        NodeMap     map_;
        struct Helper
        {
            Helper(NodeMap& map)
            : map_(map)
            {}

            void operator() ( XML_Node const& node )
            {
                map_[node.attribute("id").as_string()] = node;
            }

            NodeMap&    map_;
        }           helper_;
        XML_Node    default_;
    };

同じエラーが発生します:

IdNodeSet-B.h:38: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://cygwin.com/problems.html> for instructions.

これはロケット サイエンス コードではありません。では、何がコンパイラのコア ダンプを引き起こしているのでしょうか?

更新: プリプロセッサの出力 (つまり g++ -E から) は、どちらの場合も問題なくコンパイルされます。したがって、これは可能な回避策として認められますが、問題は残ります。回避策が実行できない状況では、どのような種類のコードを避けるべきでしょうか?

4

0 に答える 0