提升精神V2气bug与优化水平相关



我在业余时间开发代码。最好处于调试模式。最近,当我尝试构建发布版本时,我得到了错误(运行时,输出:1n2n然后失败)。我找到了包含错误的代码段(如下),发现只有当优化级别为-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++1y$INCLUDE

$WARN$OPT-o a<lt__EOF&amp/a&amp;echo-e"\e[1;32msuccessed\e[0]"||echo-e"\e[1;31m失败\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+|(/*[^*]**+([^/*][^*]**+)*/)|(//[^rn]*))"
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

gcc -v 2>&1 | tail -n1:

gcc version 4.8.1 (rev5, Built by MinGW-W64 project) 

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

关键是使用表达模板(比如Boost Proto使用的模板,以及Boost Spirit使用的模板)。它们仅在其封闭全表达式的末尾有效[1]

典型的解决方法是:

BOOST_SPIRIT_AUTO(ana, *~qi::char_('*') > +qi::char_('*'));

你可以在这里找到它: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_('*'))
;

Spirit X3承诺会去除这个疣。稍微相关一点,我认为Protox11也通过随时注意引用来消除这个问题。


[1]Grep临时工寿命延长标准。表达式模板保留对所用文字的引用(其余的无论如何都有值语义),但临时模板不绑定到(const)引用。所以它们超出了范围未定义的行为结果

最新更新