在矢量中使用擦除时双重释放或损坏(快速顶部).如何擦除一个矢量的几个项目知道它们的索引?

double free or corruption (fasttop) when using erase in vector. How can you erase several items of a vector knowing their indexes?

本文关键字:擦除 一个 几个 索引 项目 顶部 释放 损坏 何擦除      更新时间:2023-10-16

我正在做一个"大"项目,我遇到了一个分割错误,我最终缩小到一个更简单且可重现的示例:

我将放置两段代码。第一:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
std::vector<int> someVector;
printf("1n");
someVector.push_back(1);
printf("2n");
someVector.push_back(2);
printf("3n");
someVector.push_back(3);

someVector.erase(someVector.begin());
someVector.erase(someVector.begin());
return 0;
}

在这里,一切正常。好的。现在让我们尝试一些更复杂的事情。让我们使用我自己定义的类的向量,而不是使用 ints 向量。

注意:我不是专家,在定义类时可能犯了错误。类定义中存在复制构造函数的原因是参数变量实际上是指向另一个类(而不是 int(的指针,我在实际示例中将其复制到构造函数的主体上。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
class ActionType {
public:
std::string name;
int type;
int * parameters;
ActionType(const std::string _name, const int _type
);
ActionType(const ActionType &);   
~ActionType(){
// Direct implementation of destructor
printf("DELETINGn");
delete parameters;
}
};
// Implementation of initializer      
ActionType::ActionType(const std::string _name, const int _type)
: name(_name)
, type(_type)
, parameters(new int(5))
{
}
// Implementation of copy constructor
ActionType::ActionType(const ActionType & actionType)
: name(actionType.name)
, type(actionType.type)
, parameters(new int(*actionType.parameters))
{
printf("COPYINGn");
}
int main()
{
ActionType actionType("foo", 1);
std::vector<ActionType> actions;
printf("1n");
actions.push_back(actionType);
printf("2n");
actions.push_back(actionType);
printf("3n");
actions.push_back(actionType);
actions.erase(actions.begin());
actions.erase(actions.begin());
return 0;
}

这应该几乎相同,但会引发错误:

*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001618c70 ***                             
Aborted (core dumped)

问题是,在我的真实示例中,我需要一种方法来删除向量的几个项目,为此,我有这样的东西:

for (int i (...)){
int indexToDelete = getIndex();
vector.erase(vector.begin()+indexToDelete);
}

我也可以使用这样的东西:

std::vector<int> indexes;
for (int i (...)){
int indexToDelete = getIndex();
indexes.push_back(indexToDelete);
}
vector.erase(indexes);

但是我还没有想到任何可以做到这一点的功能。我见过其他答案,他们使用 sort 将所有要删除的项目放在最后和他们调用pop_back之后,但它似乎不是很干净。

无论如何,总结一下:

  • 有人知道为什么当使用带有向量的类时,函数擦除效果不佳?

  • 如何在向量中删除知道其索引的多个项目?

您缺少类的赋值运算符。std::vector要求类具有正确的复制语义,而ActionType没有正确的复制语义。

为您编写的类添加赋值运算符很简单:

#include <algorithm>
//...
class ActionType
{
//...
ActionType& operator=(const ActionType &);
//...
};
ActionType& ActionType::operator=(const ActionType &rhs)
{
if ( this != &rhs )
{
ActionType temp(rhs);
std::swap(temp.name, name);
std::swap(temp.type, type);
std::swap(temp.parameters, parameters);
}  // <-- The temp is destroyed here, along with the contents.
return *this;
}

上面使用复制/交换成语来实现赋值运算符。

请注意,添加赋值运算符时,代码现在有效。

编辑:

赋值运算符的替代形式可以是:

class ActionType
{
//...
ActionType& operator=(ActionType);
//...
};
ActionType& ActionType::operator=(ActionType temp)
{
std::swap(temp.name, name);
std::swap(temp.type, type);
std::swap(temp.parameters, parameters);
return *this;
}

删除参数数组时,需要提供一个 []

delete [] parameters;

否则,您将在程序中获得未定义的行为。

旁注> 最好将其保留为 std::vector 或 std::array。