5

我有一个指向类的指针向量。我需要调用它们的析构函数并释放它们的内存。由于它们是指针向量 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 之间的任何染色体中给出分段错误。

我不知道为什么会发生这种情况,也没有办法真正找到问题所在,因为在使用断点进行调试时,我所看到的只是它发生在随机染色体上。

我正在使用代码块 IDE 和 gdb 调试器。发生分段错误时的堆栈跟踪有 4 个内存地址和一个函数wsncpy()

4

10 回答 10

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 );
于 2009-05-21T08:43:40.053 回答
5

与 (@1800 INFORMATION) 相比略有修改的版本。

  struct DeleteFromVector
    {
        template <class T>
        void operator() ( T* ptr) const
        {
            delete ptr;
        }
    };


std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
于 2009-05-21T08:52:20.223 回答
3

我不知道您为什么会崩溃,但我想一种可能性是向量的大小与您传入的大小不同。另外我注意到您正在从 0 迭代到 size-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>());
于 2009-05-21T08:45:50.593 回答
3

顺便说一句,Boost lambda 已经有一个用于删除指针序列的函子:

std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
于 2009-05-21T09:31:07.150 回答
1

您确定向量中的每个指针都指向不同的对象吗?(即两个指针并不都指向同一个对象,您尝试删除两次。

您确定在调用此方法之前不删除某些指针吗?(即您确定列表中的每个指针都指向一个有效对象吗?)

于 2009-05-21T08:45:20.487 回答
1

最可能的原因是为同一个地址调用了两次delete 。如果您将一个对象多次添加到向量中,就会发生这种情况。要检测到这一点,请插入一些语句,该语句将输出您将删除的对象的地址。

printf( "will delete %d\n", (int)c );
delete c;
于 2009-05-21T09:35:11.430 回答
1

我发现了问题。

它可能藏在最隐蔽的地方(只不过是愚蠢的老我)。

正如一些人可能已经猜到的那样,这是一个遗传算法程序。这是我正在制作的教程。我从我制作的轮盘赌功能中随机选择染色体的交叉点。嗯......在里面,有一个-1,不应该在那里。这实际上破坏了一切,并最终导致分段错误。

谢谢大家的帮助,我在这篇文章中看到了一些非常好的做法,我打算遵循

于 2009-05-21T09:56:38.377 回答
0
void Population::clearPool(std::vector<Chromosome*>& a)
{
    for(size_t i = 0; i < a.size(); i++) {
        delete a[i];
    }

    a.clear();
}
于 2009-05-21T08:42:36.967 回答
0

我建议使用智能指针(即:auto_ptr)而不是原始指针,并且只使用 vector::clear 方法,该方法将为每个元素调用析构函数

于 2009-05-21T08:59:28.990 回答
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以避免类似的错误

于 2009-05-21T09:03:25.393 回答