【问题标题】:Memory corruption when removing elements from a vector of shared pointers从共享指针向量中删除元素时内存损坏
【发布时间】:2022-01-07 08:47:09
【问题描述】:

昨天我正在处理一个令人烦恼的错误,该错误涉及一个旨在从共享指针向量中删除元素的函数。这是有问题的代码:

template <typename T>
void flush(
    std::vector<std::shared_ptr<T>>& offers
) {
    std::vector<unsigned int> idxs;
    for (unsigned int i = 0; i < offers.size(); i++) {
        if (!offers[i]->is_available()) {
            idxs.push_back(i);
        }
    }
    for (unsigned int i : idxs) {
        offers[i] = offers.back();
        offers.pop_back();
    }
}

有时,offers 向量的元素会损坏(即它们​​会指向垃圾数据)。我最终更改了上面的代码以使用更标准的擦除删除习语:

template <typename T>
void flush(
    std::vector<std::shared_ptr<T>>& offers
) {
    offers.erase(
        std::remove_if(
            offers.begin(),
            offers.end(),
            [](std::shared_ptr<T> offer) { return !offer->is_available(); }
        ),
        offers.end()
    );
}

现在我没有看到与以前相同的问题(无论如何这更优雅)。但是,我想了解为什么在以前的代码没有的情况下它会起作用。我怀疑这与向量中保留的错误元素有关,或者可能与指针的引用计数发生了一些奇怪的事情有关,但我希望能深入了解这里到底发生了什么。

【问题讨论】:

  • 您是否检查过您的第二个循环是否最终没有访问超出范围的向量?例如:如果存储在idxs 中的这些索引之一是最后一个(并且您有多个索引要删除),那么您最终会这样做
  • 说得更极端一些,想象一下一个小数组的每个元素都被删除的情况。
  • 啊,谢谢@UnholySheep,这对我来说很明显了!不敢相信我花了这么多时间试图弄清楚这一点......

标签: c++ shared-ptr stdvector


【解决方案1】:

只需发布一个快速答案,以便将其标记为已解决。问题是第二个循环:为了使算法起作用,索引需要按降序排序;否则我们将访问越界数据。我相信以下行为应该正确:

template <typename T>
void flush(
    std::vector<std::shared_ptr<T>>& offers
) {
    std::vector<unsigned int> idxs;
    for (int i = offers.size()-1; i >= 0; i--) {
        if (!offers[i]->is_available()) {
            idxs.push_back(i);
        }
    }
    for (unsigned int i : idxs) {
        offers[i] = offers.back();
        offers.pop_back();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2011-03-30
    • 2023-03-15
    • 2015-01-03
    • 1970-01-01
    • 2015-05-26
    相关资源
    最近更新 更多