0

我正在尝试使用流程图运行一些代码,它编译成功,但是在运行时它在调用输入节点后在 tbb 流程图库文件中给出了分段错误,我似乎无法找到它的原因. 我的输入节点是这样的:

class InputNode{
public:
    // constructor, copy constructor, destructor are implemented
    bool operator() (InputResult &v){
        //some logic here that defines wether to process or not
        if(shouldProcess){
            v = InputResult();
            // some logic to set values inside v
            return true;
        } else
            return false;
    }
};

该节点连接到类型的节点tbb::flow::multifunction_node<InputResult, std::tuple<InputResult>>,连接由 完成tbb::flow::make_edge(src, firstNodeFilter);。InputResult 是一个指针,我已经检查并确认它被设置为一个有效值而不是空值。

tbb::flow::interface11::internal::broadcast_cache由函数调用try_put_task的函数抛出异常task *new_task = (*i)->try_put_task(t);tbb::flow::interface11::input_nodeapply_body_bypasstask *last_task = my_successors.try_put_task(v);

- - - - - 编辑 - - - - - -

抱歉,关于 input_node 实现的不清楚。我已经为它实现了这个代码。

tbb::flow::input_node<InputResult> src(g, InputNode());

当我尝试更改 InputNode 以匹配InputNodeBody时,在 _flow_graph_body_impl.h 中出现编译器错误:

error: no match for call to `InputResult&`
    bool operator()((Output &output) __TBB_override {return body( output ); }

并说从 tbb::flowcontrol& 到 InputResult& 没有已知的演员表

-------------edit 2 ------------ 以下包含更多我的代码,删除了一些模板可读性的参数。此代码是在升级 oneTBB 之后。

文件 1:

class NavigationQueryExecuter {
public:    
    EdgesRepoClass &edges;
    NodeRepoClass &nodes;
    LinkageRepoClass &linkage;

    NavigationQueryExecuter(NodeRepoClass& nodeRepo, EdgesRepoClass& edgeRepo, LinkageRepoClass& linkageRepo): nodes(nodeRepo),edges(edgeRepo), linkage(linkageRepo){ };

    template<class TQuery>
    TQuery* Execute(){
        typedef typename TQuery::InputResult TInputResult;
        auto query = new TQuery();
        class InputNode{
        private:
            const unsigned int Count = 1024; //const count.

            NodeRepoClass &nodes;
            TQuery& query;
            TPage* lastPage;
            TPid pid;
            const TPid lpid;
            unsigned int idx;
        public:
            InputNode(TQuery&q, NodeRepoClass& nodeRepo, TPid firstPageId, TPid lastPageId): query(q), nodes(nodeRepo), lpid(lastPageId){
                idx=0;
                pid=firstPageId;
                lastPage= nodes.GetPage(pid);
            }

            InputNode(const InputNode &other): query(other.query) ,nodes(other.nodes), pid(other.pid), lpid(other.lpid), idx(other.idx){
                lastPage = nodes.GetPage(other.lastPage->Id);
            }

            ~InputNode(){
                if(lastPage){
                    nodes.ReleasePage(lastPage);
                    lastPage= nullptr;
                }
            }

            TInputResult operator() (tbb::flow_control &fc){ //this function is invoked once only before exception is thrown.
                //logic to skip unused objects removed for simplicity.
                auto node = new NodeClass(lastPage, idx);
                while(idx < Count){
                    if(node->InUse()){
                        auto res = query.ProcessInput(node);
                        delete node;
                        return res; //res is set correctly, breaks after returning without touching any other parts of my code.
                    }
                    node->Id = ++idx;
                }
                delete node;
                fc.stop();
                return nullptr;
            }
        };
        auto g = tbb::flow::graph();
        tbb::flow::input_node<TInputResult> src(g, InputNode(*query,nodes, 0, 40));
        query->BuildGraph(g, src);
        src.activate();
        g.wait_for_all();
        return query;
    }
};

文件 2:

class QueryExample{
    EdgesRepoClass &edges;
    NodeRepoClass &nodes;
    LinkageRepoClass &linkage;
public:
    struct Result{
        int n1, n2, e1;
    };

    typedef Result* InputResult;
    typedef std::vector<InputResult> OutputResult;
    typedef tbb::flow::multifunction_node<InputResult, std::tuple<InputResult>> FilterNodeType;

    OutputResult result;

    FilterOnNode(NodeRepoClass& nodeRepo, EdgesRepoClass& edgeRepo, LinkageRepoClass& linkageRepo): nodes(nodeRepo),edges(edgeRepo), linkage(linkageRepo){
        result=OutputResult();
    }

    InputResult ProcessInput(typename NodeRepoClass::TEntry* node){
        //initialize, and process all nodes.
        Result* res = new Result();
        res->n1 = node->Id;
        return res;
    }

    void BuildGraph(tbb::flow::graph &g, tbb::flow::input_node<InputResult> &src) {

        auto firstNodeFilter = FilterNodeType(
                g,
                tbb::flow::unlimited,
                [&](const InputResult &input, typename FilterNodeType::output_ports_type &op) { 
                //processing logic can either output to connected nodes or drop unncessary nodes.
                //this function is never reached, code breaks before it.
                });
        // couple more multifunction_node are created.
        tbb::flow::make_edge(src, firstNodeFilter);
        tbb::flow::make_edge(tbb::flow::output_port<0>(firstNodeFilter), generateEdgesFilter);
        tbb::flow::make_edge(tbb::flow::output_port<0>(generateEdgesFilter), secondNodeFilter);
        tbb::flow::make_edge(tbb::flow::output_port<0>(secondNodeFilter), outputNodeFilter);

    }
};

代码在注释中文件 1 中指示的位置中断。

4

1 回答 1

0

输入节点(前源节点)与要通过引用填充的传递消息的接口存在一个缺陷,该缺陷导致在输入节点及其后继节点中可能同时使用相同的内存位置。考虑研究这个方向以找到分段错误的根本原因。

另外,考虑使用新接口,它基于 tbb::flow_control 并从节点主体返回生成的消息:input_node,它的主体要求

于 2021-02-02T05:29:07.447 回答