簡體   English   中英

C ++ std ::指針刪除和分段錯誤的向量

[英]C++ std::vector of pointers deletion and segmentation faults

我有一個指向類的指針向量。 我需要打電話給他們的析構函數並釋放他們的記憶。 因為它們是指針向量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()

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 );

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

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


std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());

我不知道你為什么會崩潰,但我想有一種可能性就是向量的大小與你傳入的大小不一樣。另外我注意到你是從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>());

Boost lambda已經有一個用於刪除指針序列的仿函數,順便說一下:

std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());

你確定向量中的每個指針指向不同的對象嗎? (即兩個指針都不指向同一個對象,你試圖刪除兩次。

在調用此方法之前,您確定不刪除某些指針嗎? (即你確定列表中的每個指針都指向一個有效的對象嗎?)

最可能的原因是為同一地址調用兩次刪除 如果您向矢量多次添加一個對象,則會發生這種情況。 要檢測此插入一些語句,將輸出您將刪除的對象的地址。

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

我發現了這個問題。

這是最隱蔽的(通過愚蠢的老我),它可能是。

有些人可能已經猜到這是遺傳算法程序。 這是我正在制作的教程。 我正在從我制作的輪盤賭功能中隨機選擇染色體的交叉點。 嗯......在那里,有一個不應該在那里的-1。 這實際上破壞了一切,並最終導致分段錯誤。

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

void Population::clearPool(std::vector<Chromosome*>& a)
{
    for(size_t i = 0; i < a.size(); i++) {
        delete a[i];
    }

    a.clear();
}

我建議使用智能指針(即:auto_ptr)而不是原始指針,只需使用vector :: clear方法,它將為每個元素調用析構函數

看來,代碼中的某些指針並未引用正確的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指針容器庫中找到有用的ptr_vector,以避免類似的錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM