std::transform 中的分段错误

Segmentation fault in std::transform

我正在尝试将解析出的文件名从正则表达式匹配传输到 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()。然而,这是为什么呢?

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

你要么需要一个你发现的 back_inserter,要么使用一些已经分配了足够 space 的容器(这只有在你提前知道你要转换多少项目的情况下才有效) .

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

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

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

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

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

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());
});

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

希望对您有所帮助!