提升与优化级别相关的Spirit V2 qi bug

Ori*_*ent 4 g++ boost-spirit compiler-optimization boost-spirit-qi

我在业余时间开发代码。最好在调试模式下。最近,当我尝试构建发行版时,出现错误(运行时,输出:1\n2\n然后失败)。我位于一段代码(下图),其中包含错误,我发现,该错误只发生,当优化级别为-Os, -Ofast, -O2, -O3但不是-O, -O0, -O1, -Og。在发布模式下,我受调试能力的限制。错误原因是什么?查找此类错误的方法是什么?

#!/ usr / bin / env bash -vex WARN =“-W -Wall -Wextra” INCLUDE =“-isystem / c / libs / boost-trunk” OPT =“-O2” g ++ -x c ++--std = gnu ++ 1年$ INCLUDE

$ WARN $ OPT -oa << __ EOF && ./a && echo -e“ \ e [1; 32msucceeded \ e [0m” || 回声-e“ \ e [1; 31mfailed \ e [0m”

#include <iterator>
#include <string>
#include <iostream>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>

using namespace boost::spirit;

template< typename Iterator >
struct skipper
        : qi::grammar< Iterator >
{

    skipper();

private :

    typename skipper::base_type::start_type skipper_;

};

template< typename Iterator >
skipper< Iterator >::skipper()
    : skipper::base_type(skipper_, "skipper") 
{
    std::cerr << 1 << std::endl;
    auto const ana =
            *~qi::char_('*') > +qi::char_('*')
            ;
    std::cerr << 2 << std::endl;
    skipper_ =
            qi::space
            | ("/*" > ana > *(~qi::char_("/*") > ana) > '/')
            | ("//" > *(qi::char_ - qi::eol) > (qi::eol | qi::eoi))
            ; // R"(\s+|(\/\*[^*]*\*+([^/*][^*]*\*+)*\/)|(\/\/[^\r\n]*))"
    std::cerr << 3 << std::endl;
}

using input_type = std::string;
using input_iterator_type = std::istreambuf_iterator< typename input_type::value_type >;
using base_iterator_type = multi_pass< input_iterator_type >;

template struct skipper< base_iterator_type >;

using skipper_type = skipper< base_iterator_type >;

int main()
{
    skipper_type const skipper_;
    std::cerr << 4 << std::endl;
    return EXIT_SUCCESS;
}
__EOF
Run Code Online (Sandbox Code Playgroud)

gcc -v 2>&1 | tail -n1

gcc version 4.8.1 (rev5, Built by MinGW-W64 project) 
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 5

这是代码中的错误,编译器或优化级别没有问题。

关键在于表达式模板(例如Boost Proto以及Boost Spirit使用的模板)。它们仅在包含完整表达式的末尾有效 [1]

规范的解决方法是:

 BOOST_SPIRIT_AUTO(ana, *~qi::char_('*') > +qi::char_('*'));
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到它:http : //svn.boost.org/svn/boost/trunk/libs/spirit/example/qi/typeof.cpp,它首先在此博客文章的评论中介绍:http:// boost-spirit.com/home/articles/qi-example/zero-to-60-mph-in-2-seconds/

我测试的显式修补程序(在我的机器上很好地工作,valgrind中没有警告):

auto const ana = boost::proto::deep_copy(
        *~qi::char_('*') > +qi::char_('*'))
        ;
Run Code Online (Sandbox Code Playgroud)

Spirit X3承诺删除此疣。有点相关,我认为Protox11还可以通过随时了解引用来消除此问题。


[1] Grep临时生命周期延长的标准。表达式模板保留对所用文字的引用(其余部分仍具有值语义),但是临时对象不绑定至(const)引用。因此,它们超出了范围。未定义行为结果

  • 在 **boost 主干**(可能它应该在下一个版本的 http://www.boost.org/libs/spirit/example/qi/typeof.cpp)中,我发现了 `boost::spirit::qi::从`#include &lt;boost/spirit/include/support_auto.hpp&gt;`复制`,也解决了问题。 (2认同)