我有一个指向类的指针。我需要打电话给他们的析构函数并释放他们的记忆。因为它们是指针向量vector.clear()不起作用。所以我继续这样做:
void Population::clearPool(std::vector<Chromosome*> a,int size)
{
Chromosome* c;
for(int j = 0 ;j < size-1;j++)
{
c = a.back();
a.pop_back();
delete c;
printf(" %d \n\r",j);
c = NULL;
}
}
那里的printf是因为我有一个会说话的析构函数,看看哪个染色体发生了分段错误。当调用clearPool()并说我们的大小为100时,它可以在0到100之间的任何染色体中给出分段错误。
我不知道为什么会发生这种情况,也没有办法真正找到错误,因为在使用断点进行调试时,我看到的是它发生在随机染色体上。
我正在使用codeblocks IDE和gdb调试器。发生分段故障时的堆栈跟踪有4个内存地址和一个函数wsncpy()
。
答案 0 :(得分:21)
void Population::clearPool( std::vector <Chromosome*> & a )
{
for ( int i = 0; i < a.size(); i++ ) {
delete a[i];
}
a.clear();
}
请注意,向量是通过引用传递的。在您的代码中,使用了向量的副本,这意味着它在调用程序中保持不变。因为你删除了副本中的指针,原来的指针现在都是无效的 - 我怀疑你使用的那些无效指针在你发布的代码中没有显示。
由于已发布了一些使用C ++库算法的模板解决方案,您可能还需要考虑不具备的模板解决方案:
template <class C> void FreeClear( C & cntr ) {
for ( typename C::iterator it = cntr.begin();
it != cntr.end(); ++it ) {
delete * it;
}
cntr.clear();
}
使用此方法可以释放任何动态分配对象的容器:
vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );
答案 1 :(得分:5)
与(@ 1800 INFORMATION)相比较轻微的修改版本。
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
答案 2 :(得分:3)
我不知道你为什么会崩溃,但我想有一种可能性是矢量的大小与你传入的大小不一样。另外我注意到你是从0到2的迭代,你不是故意一直走到最后吗?
使用惯用C ++删除数组中所有项目的一种方法是这样的:
template<class T>
class deleter
{
public:
void operator()(const T* it) const
{
delete it;
}
};
std::for_each(a.begin(), a.end(), deleter<Chromosome>());
答案 3 :(得分:3)
Boost lambda已经有一个用于删除指针序列的仿函数,顺便说一下:
std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
答案 4 :(得分:2)
您确定向量中的每个指针指向不同的对象吗? (即两个指针都没有指向同一个对象,你试图删除两次。
在调用此方法之前,您确定不删除某些指针吗? (即你确定列表中的每个指针都指向一个有效的对象吗?)
答案 5 :(得分:1)
最可能的原因是为同一地址调用 delete 两次。如果您向矢量多次添加一个对象,则会发生这种情况。要检测此插入一些语句,它将输出您将删除的对象的地址。
printf( "will delete %d\n", (int)c );
delete c;
答案 6 :(得分:1)
我发现了问题。
这是最隐蔽的(除了愚蠢的老我以外)它可能是。
有些人可能已经猜到这是遗传算法程序。这是我正在制作的教程。我正在从我制作的轮盘赌功能中随机选择染色体的交叉点。嗯......在那里,有一个不应该在那里的-1。这实际上破坏了一切,并最终导致分段错误。
谢谢大家的帮助,我在这篇文章中看到了一些非常好的做法,我打算关注
答案 7 :(得分:0)
void Population::clearPool(std::vector<Chromosome*>& a)
{
for(size_t i = 0; i < a.size(); i++) {
delete a[i];
}
a.clear();
}
答案 8 :(得分:0)
我建议使用智能指针(即:auto_ptr)而不是原始指针,只需使用将调用每个元素的析构函数的vector :: clear方法
答案 9 :(得分:0)
似乎代码中的某些指针未引用正确的Chromosome对象。如果您因代码尝试删除一些对象,则可能会发生这种情况:
Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time
您可以从Boost Pointer Container Library找到有用的ptr_vector,以避免类似的错误