段错误试图在 class 中使用 boost::spirit::qi 解析器
Segfault trying to use boost::spirit::qi parser in a class
我一直在使用 boost::spirit 编写一些解析器代码并开始出现段错误。
我已经尽可能地简化了我的代码,以便于 post,见下文。
当解析器回调 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
成员在构建语法期间指向的任何内容。
那是行不通的。
你需要一个 phoenix lazy actor,如果你希望它在你从 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))];
Note this still leaves the leaked Verilog instance in main
. Why do you use new
in modern C++?
整合它:
#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);
}
我一直在使用 boost::spirit 编写一些解析器代码并开始出现段错误。
我已经尽可能地简化了我的代码,以便于 post,见下文。
当解析器回调 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
成员在构建语法期间指向的任何内容。
那是行不通的。
你需要一个 phoenix lazy actor,如果你希望它在你从 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))];
Note this still leaves the leaked Verilog instance in
main
. Why do you usenew
in modern C++?
整合它:
#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);
}