为什么vector.erase()遇到sigabrt

Why does vector.erase() run into SIGABRT?

本文关键字:遇到 sigabrt vector erase 为什么      更新时间:2023-10-16

我的filepath归一化功能有一个奇怪的问题,我没有完全理解并且难以修复(我在c 中也不是很经验)。

/**
 * Converts any path (e.g. /a/d/../b/.//c/) to absolute /a/b/c format.
 * @param path Any valid path beginning with /
 * @return Path in absolute /a/b/c format.
 */
static std::string normalizePath(std::string path)
{
    if (path == "/")
        return "/";
    if (path[0] != '/') // full relative paths not supported due to lack of context
        return "";
    std::vector<std::string> segments = strsplit(path, '/');
    while (segments[0] == "." || segments[0] == "..")
        segments.erase(segments.begin());
    for (int i = 0; i < segments.size(); i++)
    {
        if (segments[i] == "." || segments[i].empty())
            segments.erase(segments.begin() + (i--));
        else if (segments[i] == "..")
            segments.erase(segments.begin() + (--i), segments.begin() + (i+2)); // SIGABRT
    }
    std::string r;
    for (int i = 0; i < segments.size(); i++)
        r += "/" + segments[i];
    return r;
}

与大多数输入一起工作正常,但是输入"/a/.."(应该返回"/")使其在指示的行中与SIGABRT崩溃。

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

我也不愿意使用realpath(),因为我正在使用虚拟路径,而且我绝对不希望对任何文件系统进行任何调用。

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

此行的行为不确定,因为它在彼此之间未访问访问的上下文中访问i

segments.erase(segments.begin() + (--i), segments.begin() + (i+2));

由于未指定评估顺序,并且应用副作用的顺序尚不清楚,因此segments.begin() + (i+2)可以评估到迭代器上方的迭代器。

您可以在不预先启动的情况下使用i的值来解决此问题,并在从erase返回后应用--

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

注意:上面的代码使用std::next而不是向迭代器添加数字。