Boost::精神非法_回溯异常

Boost::spirit illegal_backtracking exception

本文关键字:回溯 异常 Boost 非法      更新时间:2023-10-16

我在一个简单的计算器项目中使用Boost.SSpirit.Lex和.Qi,(像往常一样)它给我调试和使用带来了一些困难。调试打印:

<expression>
  <try>boost::spirit::multi_pass::illegal_backtracking

这个异常被抛出了,我不明白为什么。我在代码中使用宏,如果给出一个最小的例子,那将是一种痛苦,所以我给出了整个项目。只需在根执行"make",然后启动/如果您想测试,只需执行"-echoo$5-8"即可。

谷歌似乎没有发现任何类似的问题关于这个例外。。。

解析器在算术/中,解析器的调用在算术/评估器.cpp 的末尾

非常感谢任何帮助。

您的代码正在崩溃,因为BOOstrongPIRIT_QI_DEBUG和on_error<>处理程序似乎在迭代器可能无效后使用迭代器。

老实说,我不完全确定这是怎么发生的。

背景

AFAICT lexertl使用具有split_functor输入策略和split_std_deque存储策略的spirit::multipass<>[1]

现在,(幸运的是?)检查策略是buf_id_check,这意味着迭代器将在取消引用时检查是否无效。

如果

  1. 迭代器被解除围栏,将缓冲区增加到>16个标记迭代器是唯一引用共享状态的迭代器
  2. 或者沿着线clear_queue的某个地方被显式调用(例如,来自Spirit Repository中的flush_multi_path原语)

老实说,我认为这两个条件都没有得到满足。快速而肮脏的

token_iterator_type clone = iter; // just to make it non-unique...

evaluator.cpp中没有区别(排除原因#1)

暂时禁用buf_id_check_policy中的docheck实现使valgrind指出on_error<>和BOOstrongPIRIT_DEBUG*导致无效内存引用。评论确实可以消除所有问题(eval_expression现在可以工作了)。

然而,这可能不是您的首选解决方案。

建议的解决方案

  • 您正在处理一个固定的内存容器,该容器表示您并不真正需要multi_pass行为模拟的输入
  • 如果您使用的是一种琐碎的语法,那么您并没有真正从lexertl中受益,同时您会增加很多复杂性(正如您所看到的)

我很快重构了一些代码:https://github.com/sehe/sash-refactor/commits/master

  • 提交dec31496sanity - lets do without macros
    4个文件已更改,59个插入(+),146个删除(-)

  • 提交6056574cdead code, excess scope, excess instantiation
    5个文件已更改,38个插入(+),62个删除(-)

  • 提交99d441dbremove lexer
    9个文件已更改,25个插入(+),177个删除(-)

现在,您会发现您的代码通常要简单得多,也要短得多,不会遇到多路径限制,并且您仍然可以使用SPIRIT_DEBUG和on_error处理:)最终

  • -g3中的二进制大小从16Mb减少到6.5Mb
  • a已删除263行代码
  • 更重要的是,它有效

以下是一些示例(没有调试输出):

$ ./sash <<< '-echo $8-9'
    -1
    Warning: Empty environment variable "8-9".
$ ./sash <<< '-echo $8*9'
    72
    Warning: Empty environment variable "8*9".
$ ./sash <<< '-echo $8*(9-1)'
    64
    Warning: Empty environment variable "8*(9-1)".
$ ./sash <<< '-echo $--+-+8*(9-1)'
    -64
    Warning: Empty environment variable "--+-+8*(9-1)".

[1]不管它的名称如何,它都缓冲std::vector<> 中以前看到的令牌