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。
希望对您有所帮助!
我正在尝试将解析出的文件名从正则表达式匹配传输到 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。
希望对您有所帮助!