C++ 为什么vector.erase()会遇到SIGABRT?

C++ 为什么vector.erase()会遇到SIGABRT?,c++,string,vector,sigabrt,erase,C++,String,Vector,Sigabrt,Erase,我的filepath规范化函数有一个奇怪的问题,我还没有完全理解,并且在修复这个问题上遇到了困难(我对C++也不是很熟悉) /** *将任何路径(例如/a/d/./b///c/)转换为绝对/a/b/c格式。 *@param path以开头的任何有效路径/ *@返回路径为绝对/a/b/c格式。 */ 静态std::string normalizePath(std::string路径) { 如果(路径=“/”) 返回“/”; if(路径[0]!=“/”)//由于缺少上下文,不支持完整的相对路径 返回

我的filepath规范化函数有一个奇怪的问题,我还没有完全理解,并且在修复这个问题上遇到了困难(我对C++也不是很熟悉)

/**
*将任何路径(例如/a/d/./b///c/)转换为绝对/a/b/c格式。
*@param path以开头的任何有效路径/
*@返回路径为绝对/a/b/c格式。
*/
静态std::string normalizePath(std::string路径)
{
如果(路径=“/”)
返回“/”;
if(路径[0]!=“/”)//由于缺少上下文,不支持完整的相对路径
返回“”;
std::vector segments=strsplit(路径“/”);
而(段[0]==“| |段[0]==”)
segments.erase(segments.begin());
对于(int i=0;i
大多数输入都可以正常工作,但输入
“/a/。”
(应该返回
“/”
)会使它在指示行与
SIGABRT
崩溃

我的理解是,我正在删除当前和以前的元素,但显然,这个假设是错误的

我也不愿意只使用
realpath()
,因为我使用的是虚拟路径,我绝对不希望对任何文件系统进行任何调用

为什么我的代码会崩溃?
如何使其按预期工作?

此行具有未定义的行为,因为它在访问互不顺序的上下文中访问
I
两次:

segments.erase(segments.begin() + (--i), segments.begin() + (i+2));
由于未指定求值顺序,且应用副作用的顺序未知,
segments.begin()+(i+2)
可以求值到迭代器超过向量的末尾

您可以通过使用
i
的值来修复此问题,而无需预减量,并在从
擦除
返回后应用
--

else if (segments[i] == "..") {
    segments.erase(std::next(segments.begin(), i-1), std::next(segments.begin(), i+1));
    --i;
}

注意:上述代码使用而不是向迭代器中添加数字。

在同一语句中使用
--i
i+2
是自找麻烦。更不用说
i+2
可能超出范围,函数参数的求值顺序未指定。@user0042 std::remove似乎用于删除具有特定值的元素,但我想删除具有特定索引的元素。函数参数的求值顺序由实现定义。您的示例在一个参数中修改
i
,在另一个参数中访问它,但这两个求值的顺序是由实现定义的。根据顺序或计算结果,结果可能是无效范围(例如,从一开始就无法访问结束迭代器)<如果给定无效范围,则代码>矢量::擦除
具有未定义的行为。解决方案:在一个单独的语句中减量
i
,以避免此类副作用问题。@Cobra-否如果不想删除特定索引,则要删除值
”。“
。为该函数(函数或函子)编写一个测试,并使用一元谓词版本
else if (segments[i] == "..") {
    segments.erase(std::next(segments.begin(), i-1), std::next(segments.begin(), i+1));
    --i;
}