[英]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.