C ++ std ::指针删除和分段错误的向量

时间:2009-05-21 08:38:52

标签: c++ pointers memory-management segmentation-fault

我有一个指向类的指针。我需要打电话给他们的析构函数并释放他们的记忆。因为它们是指针向量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()

10 个答案:

答案 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)

我发现了问题。

这是最隐蔽的(除了愚蠢的老我以外)它可能是。

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

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

答案 6 :(得分:1)

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

printf( "will delete %d\n", (int)c );
delete c;

答案 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,以避免类似的错误