2012-01-11 9 views
1

これをほぼ半日デバッグしようとしていましたが、問題を見つけることができませんでした。ほとんどのトラブルを引き起こしているものをこの方法である:std :: list問題の原因となる要素の削除

//[datamember]  
std::list<Projectile*> m_Projectiles_l; 

//[predicate]  
bool removeDeads(Projectile* pProj) { 
    return !(pProj->isAlive()); 
} 

//[the method I think might be causing the problem] 
void ProjectileList::KillDeadProjectiles() 
{ 
    std::list<Projectile*>::iterator it; 
    it = std::remove_if(m_Projectiles_l.begin(), m_Projectiles_l.end(), &removeDeads); 

    if (it != m_Projectiles_l.end()) 
    { 
     std::list<Projectile*>::iterator itDelete; 
     for (itDelete = it; itDelete != m_Projectiles_l.end(); ++itDelete) { 
      delete (*itDelete); 
     } 
     m_Projectiles_l.erase(it, m_Projectiles_l.end()); 
    } 
} 

VS2010ブレークエラー:

Unhandled exception at 0x00389844 in PsychoBots.exe: 0xC0000005: Access violation reading location 0xfeeeff3a. 

ブレーキングは、この行に私をもたらします:

void ProjectileList::DoPhysicsStuff(const InputState& refInputState) 
{ 
    KillDeadProjectiles(); 

    std::list<Projectile*>::iterator it; 
    for (it = m_Projectiles_l.begin(); it != m_Projectiles_l.end(); ++it) { 
/*[THIS line]*/(*it)->DoPhysicsStuff(refInputState); 
    } 
} 

私の調査結果:

It gives a problem when: there are more than 2 elements in the list, and a "projectile that has been added to the list earlier than a projectile that has been added later on" is getting removed with this method.

It gives no problems when: There is only one element in the list OR All the elements are getting removed at the same time.

誰にでもこれのエラー?

もっとコードが必要な場合は、コメントしてください。私は今は小さなサイズにしています。

+3

イテレータを 'remove_if'の結果を超えて使用することはできません。それらを消去することはできますが、特定の状態になることは保証されていないため、アクセスしないでください。しかし、この時間を無駄にすることなく、生のポインタの使用をやめてください。 –

+0

@KerrekSB私は「私はそれらを使うことが許されていないので、スマートポインタについてのコメントはしないでください」というコメントにほとんど追加しました;しかし、人々はそれについてコメントしたいと思っています。 – xcrypt

答えて

2

remove_ifが返すイテレータ以外のコンテナの内容に依存することはできません。つまり、コンテナ内の動的メモリを管理する場合は、別のアプローチをとる必要があります。簡単な方法は、生ポインタの代わりにshared_ptrオブジェクトを保存することです。それでは、消去消去イディオムを使用すれば、すべてがクリーンアップされます。そうでない場合は、remove_ifの代わりに、削除メカニズムを慎重に書く必要があります。

1

std :: remove_if()のリファレンスをよく読んでください。

"it"から "m_Projectiles_l.end()"の範囲の値は有効ですが、その値は指定されていません。ほとんどの場合、これらの値は実装に応じて変更されません。

このようにして、要素が新しいリストに含まれていても、古いリストの末尾に残っている可能性があります。この要素を削除すると、メモリ例外が発生します。

参照されなくなった要素を削除する別の方法を見つける必要があります。スマートポインタを考慮する。

+0

はい私はdefする必要があります。次回はリファレンスを読むほうがいい:) – xcrypt

関連する問題