【问题标题】:Segmentation fault in std::transformstd::transform 中的分段错误
【发布时间】:2015-09-11 04:45:33
【问题描述】:

我正在尝试将解析出的文件名从正则表达式匹配转移到filesystem::path 对象列表。

我相信匹配是有效的,因为 for_each 对于相同的迭代器和打印到控制台工作得很好。但是,我在运行此代码时遇到了分段错误。我究竟做错了什么?我的 lambda 有错误吗?

        namespace fs = boost::filesystem;
        std::forward_list<fs::path> results;
        std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re),
                       std::sregex_iterator(), results.begin(),
                       [&](const std::smatch& m)->fs::path{
            return root / fs::path(m[1].str());
        });

GDB 将这一行显示为错误的地方:

path& operator=(const path& p)
{
  m_pathname = p.m_pathname;
  return *this;
}

更新:找到解决方案 - 使用 back_inserter(results) 而不是 results.begin()。但是,这是为什么呢?

【问题讨论】:

  • 您确定您使用的是back_inserter,而不是front_inserterforward_list 没有 push_back 函数,所以 back_inserter 不应该使用它。

标签: c++ regex lambda boost-filesystem


【解决方案1】:

std::transform 算法的第三个参数应该是一个迭代器,指向应该写入值的范围的开头。具体来说,它通过用转换后的值覆盖迭代器指向的范围内的值来工作。这意味着实际上必须首先在那里覆盖值。在你的情况下,你正在写一个空的forward_list,所以没有什么可写的,因此崩溃了。

要解决此问题,请考虑将最后一个参数替换为 back_inserter,这将在生成值时自动创建所需的空间:

std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re),
               std::sregex_iterator(),
               back_inserter(results), // <--- This is new
               [&](const std::smatch& m)->fs::path{
        return root / fs::path(m[1].str());
});

更一般地说,据我所知,&lt;algorithm&gt; 中写入输出范围的所有算法都假定在该范围内有可覆盖的值。如果不是这种情况,请考虑使用 back_inserter 或其他类型的插入迭代器,它会自动为您创建所需的空间。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您的输出迭代器是一个简单的results.begin(),可能是== results.end()。这里的线索是尝试分配结果时失败。

    你要么需要一个back_inserter,就像你找到的那样,要么使用一些已经分配了足够空间的容器(只有在你事先知道要转换多少个项目时才能工作)。

    具体来说,考虑第一个重载here的示例实现。

    线

    *d_first++ = op(*first1++);
    

    要求目标迭代器已经有效。如果按照提示是== end(),则整个操作都是非法的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2012-02-10
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多