簡體   English   中英

Segfault試圖在類中使用boost :: spirit :: qi解析器

[英]Segfault trying to use boost::spirit::qi parser in a class

我一直在使用boost :: spirit編寫一些解析器代碼,並開始出現段錯誤。

為了使發布變得容易,我已盡力簡化了代碼,請參見下文。

當解析器回調到addModule時,會在int的推回過程中發生段錯誤。

Valgrind聲稱矢量v_modules沒有初始化。 在代碼的前面,我可以看到它已初始化,因此我假設正在發生一些內存破壞。 我試圖用這個較小的測試用例重寫它很多次,但是沒有用。 任何幫助表示贊賞!

verilog.cpp:

#include "verilog.h"
#include <string>
#include <boost/spirit/include/qi.hpp>

Verilog::Verilog() {
  m_parser.verilog = this;
}
Verilog::~Verilog(){}

void Verilog::parse(string contents) {
  string::const_iterator iter = contents.begin();
  string::const_iterator end = contents.end();
  bool r = phrase_parse(iter,end,m_parser,boost::spirit::ascii::space);
}

void Verilog::addModule() {
  int new_mod = 1;
  v_modules.push_back(new_mod);
}

int main()
{
  Verilog* verilog = new Verilog();
  string contents = "hello";
  verilog->parse(contents);
}

verilog.h

#ifndef VERILOG_H
#define VERILOG_H

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/bind.hpp>

using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

class Verilog
{

 public:
  Verilog();
  ~Verilog();
  void parse(string contents);
  void addModule() ;

  template <typename Iterator>
    struct verilog_parser : qi::grammar<Iterator, ascii::space_type>  
    {
    verilog_parser() : verilog_parser::base_type(module)
        {
          module = qi::eps[boost::bind(&Verilog::addModule, verilog)];
        }

      qi::rule<Iterator, ascii::space_type> module;

      Verilog* verilog;

    };

 private:
  std::vector<int>    v_modules;
  verilog_parser<string::const_iterator> m_parser;

};

#endif

您正在使用boost::bind ,這將導致一個臨時函數對象,該對象引用語法構造過程中verilog成員指向的內容。

那是行不通的。

您需要一個鳳凰懶惰角色,如果您希望一旦從Verilog構造函數中設置更改后的值,就可以通過_reference使其引用this->verilog

老實說,代碼看起來有些笨拙。 為什么不使用Spirit的屬性兼容性規則為您自動構建向量(或列表,集合,地圖等)?

解決方法:

#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;

// ... later

            module = qi::eps[phx::bind(&Verilog::addModule, phx::ref(verilog))];

注意,這仍然將泄漏的Verilog實例留在main 為什么在現代C ++中使用new

集成它:

生活在Coliru

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/bind.hpp>

using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;

class Verilog {

  public:
    Verilog();
    ~Verilog();
    void parse(string contents);
    void addModule();

    template <typename Iterator> struct verilog_parser : qi::grammar<Iterator, ascii::space_type> {
        verilog_parser() : verilog_parser::base_type(module) {
            module = qi::eps[phx::bind(&Verilog::addModule, phx::ref(verilog))];
        }

        qi::rule<Iterator, ascii::space_type> module;

        Verilog *verilog;
    };

  private:
    std::vector<int> v_modules;
    verilog_parser<string::const_iterator> m_parser;
};

#include <string>
#include <boost/spirit/include/qi.hpp>

Verilog::Verilog() { m_parser.verilog = this; }
Verilog::~Verilog() {}

void Verilog::parse(string contents) {
    string::const_iterator iter = contents.begin();
    string::const_iterator end = contents.end();
    bool r = phrase_parse(iter, end, m_parser, boost::spirit::ascii::space);
}

void Verilog::addModule() {
    int new_mod = 1;
    v_modules.push_back(new_mod);
}

int main() {
    Verilog verilog;
    string contents = "hello";
    verilog.parse(contents);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM