Boost :: spirit illegal_backtracking异常

时间:2013-11-19 18:51:27

标签: c++ boost-spirit boost-spirit-qi boost-spirit-lex

我使用Boost.Spirit.Lex和.Qi作为一个简单的计算器项目,并且(像往常一样)它给我一些调试和使用的痛苦。调试打印:

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

抛出此异常,我无法理解原因。我在我的代码中使用宏,给出一个最小的例子是很痛苦所以我给了whole project。只需在root上执行“make”,然后启动./sash,会出现一个提示,如果你想测试只做“-echo $ 5-8”。

Google似乎没有发现任何有关此异常的类似问题......

解析器处于arithmetic /中,解析器的调用位于arithmetic / evaluator.cpp的末尾

任何帮助都非常感激。

1 个答案:

答案 0 :(得分:3)

您的代码正在破坏,因为BOOST_SPIRIT_QI_DEBUG以及on_error<>处理程序似乎在它们可能已失效后使用迭代器。

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

背景

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

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

如果

,预计迭代器将失效
  1. 迭代器被解除反射,将缓冲区增加到&gt; 16个标记 迭代器是唯一一个引用共享状态的文件。
  2. 或沿着clear_queue行的某个地方被明确地称为(例如来自Spirit Repository中的flush_multi_path原语)
  3. 老实说,我没有看到满足这两个条件中的任何一个。快速而肮脏

    token_iterator_type clone = iter; // just to make it non-unique...
    
    evaluator.cpp中的

    没有区别(排除原因#1)

    临时禁用docheck中的buf_id_check_policy实现使得valgrind指出on_error<>和BOOST_SPIRIT_DEBUG *导致无效的内存引用。评论两者确实会使所有问题都消失(eval_expression现在可以正常工作)。

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

    提议的解决方案

    • 您正在处理一个固定的内存容器,表示您不需要multi_pass行为模拟的输入
    • 你正在使用一个简单的语法,你并没有真正受益于 lexertl - 当你得到很多额外的复杂性时(如你所见)

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

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

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

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

    现在,您会发现您的代码通常更简单,更短,没有遇到multi_pass限制,您仍然可以使用SPIRIT_DEBUG以及on_error处理:)最后

    • -g3中的二进制文件大小 从16Mb减少到6.5Mb
    • 净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<>

    中看到的令牌