您的代码正在破坏,因为 BOOST_SPIRIT_QI_DEBUG 以及on_error<>
处理程序似乎在迭代器可能已失效后使用了迭代器。
老实说,我不完全确定这是怎么发生的。
背景
AFAICT lexertlspirit::multipass<>
与split_functor
输入策略和split_std_deque
存储策略[1]一起使用。
现在,(幸运的是?)检查策略buf_id_check
意味着迭代器将在取消引用时检查无效。
如果出现以下情况,则迭代器预计会失效
- 迭代器被取消引用,将缓冲区增加到> 16个令牌,并且迭代器是唯一引用共享状态的迭代器。
- 或沿线的某个地方
clear_queue
被明确地调用(例如,来自flush_multi_path
精神库中的原语)
老实说,我没有看到满足这两个条件中的任何一个。一个又快又脏
token_iterator_type clone = iter; // just to make it non-unique...
inevaluator.cpp
没有区别(排除原因#1)
在制作的 valgrind 中临时禁用docheck
实现buf_id_check_policy
指出on_error<>
和 BOOST_SPIRIT_DEBUG* 导致无效的内存引用。评论两者确实使所有问题都消失了(eval_expression
现在有效)。
但是,这可能不是您的首选解决方案。
建议的解决方案
自从
- 您正在处理一个固定的内存容器,表示您并不真正需要
multi_pass
行为仿真的输入
- 您使用的是微不足道的语法,但您并没有真正从lexertl中受益——而您却获得了很多额外的复杂性(如您所见)
我很快重构了一些代码:https ://github.com/sehe/sash-refactor/commits/master
提交 dec31496
4 个文件已更改,59 次插入(+),146 次删除(-)sanity - lets do without macros
提交 6056574c
5 个文件更改,38 次插入(+),62 次删除(-)dead code, excess scope, excess instantiation
提交 99d441db
9 个文件更改,25 次插入(+),177 次删除(-)remove lexer
现在,您会发现您的代码通常更简单,也更短,没有遇到 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<>