在向量中使用擦除时出现双重释放或损坏 (fasttop)。如何在知道索引的情况下删除向量的多个项目?
double free or corruption (fasttop) when using erase in vector. How can you erase several items of a vector knowing their indexes?
我正在做一个 "big" 项目,但遇到了分段错误,我最终将其缩小为一个更简单且可重现的示例:
我要放两段代码。第一:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
std::vector<int> someVector;
printf("1\n");
someVector.push_back(1);
printf("2\n");
someVector.push_back(2);
printf("3\n");
someVector.push_back(3);
someVector.erase(someVector.begin());
someVector.erase(someVector.begin());
return 0;
}
在这里,一切正常。行。现在让我们尝试一些更复杂的东西。我们不使用整数向量,而是使用我自己定义的向量 class。
注意:我不是专家,我在定义class时可能犯了错误。 class 定义中有复制构造函数的原因是因为 parameters 变量实际上是指向另一个 class (而不是 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("DELETING\n");
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("COPYING\n");
}
int main()
{
ActionType actionType("foo", 1);
std::vector<ActionType> actions;
printf("1\n");
actions.push_back(actionType);
printf("2\n");
actions.push_back(actionType);
printf("3\n");
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 之后删除,但它看起来不是很干净。
无论如何,在摘要中:
有人知道为什么将 class 与 vector 一起使用时,擦除功能效果不佳吗?
我如何删除几个已知其在矢量中的索引的项目?
您缺少 class 的赋值运算符。 std::vector
要求您的 class 具有正确的复制语义,而您的 ActionType
没有正确的复制语义。
为您写的 class 添加赋值运算符很简单:
#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;
}
以上使用copy / swap习语来实现赋值运算符
注意添加赋值运算符时的代码now works
编辑:
赋值运算符的替代形式可以是:
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。
我正在做一个 "big" 项目,但遇到了分段错误,我最终将其缩小为一个更简单且可重现的示例:
我要放两段代码。第一:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
std::vector<int> someVector;
printf("1\n");
someVector.push_back(1);
printf("2\n");
someVector.push_back(2);
printf("3\n");
someVector.push_back(3);
someVector.erase(someVector.begin());
someVector.erase(someVector.begin());
return 0;
}
在这里,一切正常。行。现在让我们尝试一些更复杂的东西。我们不使用整数向量,而是使用我自己定义的向量 class。
注意:我不是专家,我在定义class时可能犯了错误。 class 定义中有复制构造函数的原因是因为 parameters 变量实际上是指向另一个 class (而不是 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("DELETING\n");
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("COPYING\n");
}
int main()
{
ActionType actionType("foo", 1);
std::vector<ActionType> actions;
printf("1\n");
actions.push_back(actionType);
printf("2\n");
actions.push_back(actionType);
printf("3\n");
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 之后删除,但它看起来不是很干净。
无论如何,在摘要中:
有人知道为什么将 class 与 vector 一起使用时,擦除功能效果不佳吗?
我如何删除几个已知其在矢量中的索引的项目?
您缺少 class 的赋值运算符。 std::vector
要求您的 class 具有正确的复制语义,而您的 ActionType
没有正确的复制语义。
为您写的 class 添加赋值运算符很简单:
#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;
}
以上使用copy / swap习语来实现赋值运算符
注意添加赋值运算符时的代码now works
编辑:
赋值运算符的替代形式可以是:
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。