【问题标题】:boost::any_range with optimization level -O2 causes crash优化级别为 -O2 的 boost::any_range 导致崩溃
【发布时间】:2017-07-14 14:55:22
【问题描述】:

这段代码有什么问题:

#include <iostream>
#include <vector>

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/any_range.hpp>


using namespace boost::adaptors;


using Range =
  boost::any_range<
    int,
    boost::forward_traversal_tag,
    int,
    std::ptrdiff_t>;


void magic(const Range &) {}


int main()
{
  std::vector<int> xs{0, 1, 2};

  auto ys = xs | transformed([](auto x) { return x; });

  const Range zs = ys;
  std::vector<int> us{boost::begin(zs), boost::end(zs)};
  magic(us);

  return 0;
}

遵守:

c++ -g -std=c++14 -O2 main.cpp

运行并获取 segfault

但是当我以较低的优化级别进行编译时,一切正常。

gdb 输出:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004011a5 in boost::range_detail::any_iterator<int, boost::iterators::forward_traversal_tag, int, long, boost::any_iterator_buffer<64ul> >::dereference (this=<optimized out>) at /usr/include/boost/range/detail/any_iterator.hpp:512
512                     return m_impl->dereference();

这是boost::any_range 错误,还是我滥用了库?

如果我这样编译程序也会崩溃:

c++ -g -std=c++14 -O1 -fisolate-erroneous-paths-dereference main.cpp

如果我使用选项-O1 -fisolate-erroneous-paths-dereference 编译它,下面的程序也会崩溃:

#include <iostream>
#include <vector>

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/any_range.hpp>


using namespace boost::adaptors;


using Range =
  boost::any_range<
    int,
    boost::forward_traversal_tag,
    int &,
    std::ptrdiff_t>;


void magic(const Range &xs) {
  for (auto x: xs) { std::cout << xs; }
}


int main()
{
  std::vector<int> xs{0, 1, 2};
  auto ys = xs | transformed([](auto x) { return x; });
  magic(ys);
  return 0;
}

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    这是boost bug 10493,与10360相关,在1.56(2014-08)中引入,最终通过fix PR #941.74 (2020-08)中修复

    在 1.74 之前,问题在于,它不仅仅使用您的 reference 类型,而是将其包装在 mutable_reference_type_generator 中,这会阻止您返回临时值。也就是说,当你写:

    using Range =
      boost::any_range<
        int,
        boost::forward_traversal_tag,
        int,
        std::ptrdiff_t>;
    

    您将reference 类型明确指定为int,而不是int&amp;,因为您的范围基本上是一个输入范围。但是无论如何,boost 的内部结构都将其更改为int&amp;,因此您悬而未决。当您编写 const int intsead 的 int 时,类型特征不会添加引用,因此您实际上确实以 const int 结束。

    【讨论】:

      【解决方案2】:

      实际上,当我输入问题的标题时,this question 被提供为可能的答案。

      按照问题答案中的建议,我将 int 替换为 const int 并且它起作用了:

      using Range =
        boost::any_range<
          int,
          boost::forward_traversal_tag,
          const int,
          std::ptrdiff_t>;
      

      我决定发布该问题,因为引用的问题未标记为已回答。

      【讨论】:

        猜你喜欢
        • 2013-05-26
        • 2016-02-05
        • 2013-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 2012-04-24
        相关资源
        最近更新 更多