2017-02-28 6 views
2

私はクラスとして、文字列のデキューとメンバとしてのイテレータを持っています。 GetNext()メソッドは私に次の要素を与え、イテレータをインクリメントします。外部からのクラスを使用して、私は両端キューの終了を示す空の文字列をチェックします。 残念ながら、コンストラクタが呼び出され、GetNextを使用して最後の要素が取得されると、ヒープの破損が発生します。 これは、両端キュー内の最後の文字列(空の文字列)の後にイテレータがインクリメントされ、メモリ内にのどこかにがあるためです。 デストラクタがこのメモリを解放しようとすると、クラッシュします。const_iteratorメンバを持つクラスのデストラクタを呼び出すときのヒープの破損

#include <iostream> 
#include <string> 
#include <deque> 


class Foo 
{ 
public: 
    Foo() 
    { 
     list.push_back("first elm"); 
     list.push_back("second elm"); 
     list.push_back(std::string());  
     pNextItem = list.begin(); 
    } 

    virtual ~Foo(){} 

    const std::string& GetNext() { return *pNextItem++; } 

protected: 

    std::deque<std::string> list; 
    std::deque<std::string>::const_iterator pNextItem; 
}; 


int main() 
{ 
    { 
    Foo foo; 
    std::cout << foo.GetNext() << std::endl; // "first elm" 
    std::cout << foo.GetNext() << std::endl; // "second elm" 
    std::cout << foo.GetNext() << std::endl; // "" 
    //third call sets the iterator past the last element and causes a segfault 
    std::cout << foo.GetNext() << std::endl; 

    } 

} 

ここでは例です: Compilable and executable Example

+0

私は例を編集して、tutorialspoint.comのコンパイル可能コードへのリンクを含めました – tzippy

答えて

3

あなたはpNextItemが逆参照する前にlist.cend()に等しいかどうかを確認する必要があります。これはまさにfoo.GetNext()の3番目の呼び出しの後に起こります。最後の要素を間接参照し、イテレータをインクリメントします。 deque::endreferenceから

は コンテナの最後の要素、次の要素へのイテレータを返します。

この要素はプレースホルダとして機能します。アクセスしようとすると、定義されていない動作の が発生します。

+0

私はクラスを使用するコードを追加しました。 – tzippy

+0

@tzippyだから私は良い推測をした:)答えを更新しました。 – AMA

+0

非常によく推測;)答えをありがとう。これは代わりに良い方法だろうか? : 'のconstのstd ::文字列&GetNextの(){ \t場合(pNextItem == list.end()) \t \tリターン*のpNextItem。 \t return * pNextItem ++; } ' – tzippy

関連する問題