在提升::精神::lex 中的访问冲突
Access violation in boost::spirit::lex
我已经将代码减少到重现错误所需的绝对最小值(可悲的是,这仍然是 60 行,不是很 Minimal,但至少是它的 VCE(。
我在Visual Studio 2013(Platform Toolset v120(中使用Boost 1.56。
下面的代码给了我一个访问冲突,除非我取消注释标记的行。通过做一些测试,如果枚举从 0 开始,似乎 boost::spirit 不喜欢它(在我的完整代码中,我在枚举中有更多的值,我只是设置了IntLiteral = 1
,它也摆脱了访问违规错误,尽管名称是错误的,因为 ToString 在索引到数组时偏离了一个(。
这是 boost::spirit 中的错误还是我做错了什么?
#include <iostream>
#include <string>
#include <vector>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
namespace lex = boost::spirit::lex;
typedef lex::lexertl::token<char const*> LexToken;
typedef lex::lexertl::actor_lexer<LexToken> LexerType;
typedef boost::iterator_range<char const*> IteratorRange;
enum TokenType
{
//Unused, // <-- Uncommenting this fixes the error (1/2)
IntLiteral,
};
std::string tokenTypeNames[] = {
//"unused", // <-- Uncommenting this line fixes the error (2/2)
"int literal",
};
std::string ToString(TokenType t)
{
return tokenTypeNames[t];
}
template <typename T>
struct Lexer : boost::spirit::lex::lexer < T >
{
Lexer()
{
self.add
// Literals
("[1-9][0-9]*", TokenType::IntLiteral);
}
};
int main(int argc, char* argv[])
{
std::cout << "Boost version: " << BOOST_LIB_VERSION << std::endl;
std::string input = "33";
char const* inputIt = input.c_str();
char const* inputEnd = &input[input.size()];
Lexer<LexerType> tokens;
LexerType::iterator_type token = tokens.begin(inputIt, inputEnd);
LexerType::iterator_type end = tokens.end();
for (; token->is_valid() && token != end; ++token)
{
auto range = boost::get<IteratorRange>(token->value());
std::cout << ToString(static_cast<TokenType>(token->id())) << " (" << std::string(range.begin(), range.end()) << ')' << std::endl;
}
std::cin.get();
return 0;
}
如果我取消注释我得到的行:
Boost version: 1_56
int literal (33)
如果你取消注释这些行,它"有效"的事实纯粹是偶然的。
从文档中 spirit/lex/tutorials/lexer_quickstart2.html:
为了确保每个令牌都被分配一个id,Spirit.Lex库在内部为令牌定义分配了唯一的编号,从
boost::spirit::lex::min_token_id
定义的常量开始
另请参阅此较旧的答案:
- Spirit Lex:哪个令牌定义生成了此令牌?
因此,您可以使用偏移量来修复它,但我想它将继续是一个脆弱的解决方案,因为很容易让枚举与词法分析器表中的实际令牌定义不同步。
我建议使用链接答案中给出的nameof()
方法,该方法利用命名token_def<>
对象。
住在科里鲁
#include <iostream>
#include <string>
#include <vector>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
namespace lex = boost::spirit::lex;
typedef lex::lexertl::token<char const*> LexToken;
typedef lex::lexertl::actor_lexer<LexToken> LexerType;
typedef boost::iterator_range<char const*> IteratorRange;
enum TokenType {
IntLiteral = boost::spirit::lex::min_token_id
};
std::string const& ToString(TokenType t) {
static const std::string tokenTypeNames[] = {
"int literal",
};
return tokenTypeNames[t - boost::spirit::lex::min_token_id];
}
template <typename T>
struct Lexer : boost::spirit::lex::lexer<T> {
Lexer() {
this->self.add
// Literals
("[1-9][0-9]*", TokenType::IntLiteral);
}
};
int main() {
std::cout << "Boost version: " << BOOST_LIB_VERSION << std::endl;
std::string input = "33";
char const* inputIt = input.c_str();
char const* inputEnd = &input[input.size()];
Lexer<LexerType> tokens;
LexerType::iterator_type token = tokens.begin(inputIt, inputEnd);
LexerType::iterator_type end = tokens.end();
for (; token->is_valid() && token != end; ++token)
{
auto range = boost::get<IteratorRange>(token->value());
std::cout << ToString(static_cast<TokenType>(token->id())) << " (" << std::string(range.begin(), range.end()) << ')' << std::endl;
}
}
相关文章:
- 写入位置0x0000000C时发生访问冲突
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 链表中写入访问冲突的未知原因
- C++中的openCV Mat访问冲突
- C++尝试深度复制唯一指针时出现内存访问冲突
- C++ 中动态二维数组的访问冲突
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- 写入访问冲突异常
- 在类 12.exe 中0x7B37FF80 (ucrtbased.dll) 引发异常: 0xC0000005:访问冲突读
- 0xC0000005:访问冲突写入位置0xCDCDCDCD动态分配错误
- 读取访问冲突.这0xCDCDCDCD
- 0xC0000005:访问冲突读取位置 0x00000000. 重载 == 运算符的问题
- 插入数组时违反写访问冲突
- 使用 ReadProcessMemory 获取字符串值的访问冲突
- 尝试通过共享指针使用变量时读取访问冲突
- 堆栈上的 C++ 访问冲突写入异常
- 引发异常:写访问冲突. temp 为 nullptr
- 将静态字符数组中的字符分配给动态分配的字符数组 - 访问冲突
- 在C++中删除双向链表的头节点后出现访问冲突异常
- 在提升::精神::lex 中的访问冲突