Boost Spirit拆分表达式后Debug正常Release模式解析失败问题
问题根因
Boost.Spirit Qi的解析器基于表达式模板技术实现,设计为惰性求值,仅在qi::parse等解析接口触发时才实际执行匹配逻辑,组合解析器的过程中,所有子解析器默认以引用形式存储,不会做深拷贝。
你使用auto X19 = qi::lit(" ") | qi::lit(" 0.000000000000D+00");写法时,|操作符返回的是临时的组合解析器对象,其内部持有的两个qi::lit实例都是当前语句内的临时对象引用。这条赋值语句执行结束后,两个qi::lit临时对象就会被销毁,X19内部存储的就变成了悬垂引用。
Debug模式下编译器不会对临时对象的内存做即时回收或覆写,悬垂引用碰巧能访问到原始值,因此看起来运行正常;Release模式下编译器开启内存优化,临时对象的内存会被立刻回收复用,X19访问到非法内存,自然无法得到正确的解析结果。
修复方案
- 方案1:直接将组合逻辑写在
qi::parse的参数中,也就是你第二个示例的写法。所有临时解析器对象的生命周期会被自动延长到qi::parse调用结束,不会出现悬垂问题。 - 方案2:如果需要拆分复用解析器,使用
qi::copy对组合表达式做深拷贝,将临时对象的内容复制到持久化实例中:
auto X19 = qi::copy(qi::lit(" ") | qi::lit(" 0.000000000000D+00"));
- 方案3:将拆分的解析器定义为
qi::rule类型,rule类型会自动对表达式做内部持久化存储,也不会出现悬垂引用问题:
qi::rule<std::string::const_iterator> X19 = qi::lit(" ") | qi::lit(" 0.000000000000D+00");
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

