2017-09-17 12 views
0

クラスの静的メンバーとしてベクトルを使用して、クラス自体とその派生クラスのすべてのインスタンスを数えます。しかし、コンテナのサイズを変更しようとすると、ベクター自体からスローされたスタックオーバーフローが発生します。C++クラスインスタンスの静的コンテナとしてベクトルを使用

// initialize static values: 
    auto_ptr<HandleManager> ID3OBJ::HM = auto_ptr<HandleManager>(new HandleManager()); 
    auto_ptr<vector<shared_ptr<ID3OBJ>>> ID3OBJ::ObjectList = auto_ptr<vector<shared_ptr<ID3OBJ>>>(new vector<shared_ptr<ID3OBJ>>{}); 

静的メンバーを上記のように空の状態で初期化します。

// constructors: 
     ID3OBJ::ID3OBJ(double x, double y, double z) : X(x), Y(y), Z(z), Handle(this->HM->addHandle()) { ObjectList->push_back(auto_ptr<ID3OBJ>(this));} 
     ID3OBJ::ID3OBJ() : X(0), Y(0), Z(0), Handle(this->HM->addHandle()) { ObjectList->push_back(shared_ptr<ID3OBJ>(this));} 

     Vector::Vector(double x, double y, double z) { X = x; Y = y; Z = z; 
     ObjectList->push_back(auto_ptr<Vector>(this));} 
     Vector::Vector() { 
      X = 0; Y = 0; Z = 0; 
      ObjectList->push_back(shared_ptr<Vector>(this));} 

コンストラクタは、インスタンスインスタンスにObjectListという新しいインスタンスを追加します。これは意図したとおりに動作しています。

// deconstructors: 
    ID3OBJ::~ID3OBJ() 
    { 
     string tempH = this->Handle; 
     auto iter = ObjectList->end(); 
     if (ObjectList->size() == HM->assignedHandles()) 
     { 
      iter = remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; }); 
     } 
     ObjectList->erase(iter, ObjectList->end()); 
     this->HM->removeHandle(this->Handle); 
    } 

    Vector::~Vector() 
    { 
     string tempH = this->Handle; 
     auto iter = ObjectList->end(); 
     if (ObjectList->size() == HM->assignedHandles()) 
     { 
      iter=remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; }); 
     } 
     ObjectList->erase(iter, ObjectList->end()); 
    } 

は、私の知る限り理解しremove_ifは、そのPREDのoccurance後の要素を持つ真を返す任意の回出てくる置き換えます。 vec [3]を引数とするpredがtrueを返す場合、vec [2]はvec [3]の代わりにvec [4]を指します。 したがって、コンテナの長さを短くするには消去機能が必要ですが、この短縮を実装するとすぐにエラーが発生します。

ヘッダーファイル:

// class-name:  ID3OBJ 
    // Date:   30.01.2017 
    // Version:   1.0 
    // Description:  The class works as base class for all used 3D-Objects, and defines the operations all 3D-Objects have, namely the Direction in case of a vector, or origion in all other cases 
    // 

    class ID3OBJ 
    { 
    public: 
     double X; 
     double Y; 
     double Z; 
     static auto_ptr<vector<shared_ptr<ID3OBJ>>> ObjectList; 

     ID3OBJ(double x, double y, double z); 
     ID3OBJ(); 
     ~ID3OBJ(); 
     const string getHandle(); 

    protected: 
     string Handle; 
     static auto_ptr<HandleManager> HM; 
    }; 

    // class-name:  I3DM 
    // Date:   23.03.2017 
    // Version:   1.0 
    // Description:  The class works as Interface for classes which can do Vector-operations 
    // 
    template <class T> class I3DM : public virtual ID3OBJ 
    { 
    public: 
     using ID3OBJ::X; 
     using ID3OBJ::Y; 
     using ID3OBJ::Z; 

     static auto_ptr<vector<shared_ptr<T>>> ObjectList; 
    protected: 
     using ID3OBJ::Handle; 
     using ID3OBJ::HM; 
    }; 
    // class-name:  Vector 
    // Date:   30.01.2017 
    // Version:   1.0 
    // Description:  The class works as vector, it provides an interface to acces and modify vectors, aswell as most of the vector operations 
    // 
    class Vector : public virtual I3DM<Vector> 
    { 
    public: 
     using I3DM<Vector>::X; 
     using I3DM<Vector>::Y; 
     using I3DM<Vector>::Z; 
     using I3DM<Vector>::ObjectList; 
     Vector(double x, double y, double z); 
     Vector(); 
     ~Vector(); 
    //I'm not sure if the protected members have to be provided aswell in the header file 
    protected: 
     using ID3OBJ::Handle; 
     using ID3OBJ::HM; 
    }; 

HM-ヘッダ:

class HandleManager 
    { 
    public: 
     HandleManager(); 
     const int assignedHandles(); 
     const string addHandle(); 
     void removeHandle(string hexstring); 
    protected: 
     int AssignedHandles; 
     forward_list<int> FreeHandles; 
     bool FreeHandlesAvailable; 
    }; 

CPP:

const int string_to_hex(string s) 
{ 
    int returnvalue; 
    stringstream stream; 
    stream << hex << s; 
    stream >> returnvalue; 
    return returnvalue; 
} 
HandleManager::HandleManager() 
{ 
    this->FreeHandlesAvailable = false; 
    this->AssignedHandles = 0; 
} 
const int HandleManager::assignedHandles() 
{ 
    return this->AssignedHandles; 
} 
const string HandleManager::addHandle() 
{ 
    string returnValue; 
    if (this->FreeHandlesAvailable) 
    { 
     returnValue = int_to_hex(this->FreeHandles.front()); 
     this->FreeHandles.pop_front(); 
     this->AssignedHandles++; 
     if (this->FreeHandles.empty()) { this->FreeHandlesAvailable = false; } 
    } 
    else 
    { 
     returnValue = int_to_hex(this->AssignedHandles); 
     this->AssignedHandles++; 
     if (this->AssignedHandles == 1) { returnValue = int_to_hex((int)0); } 
     } 
    return returnValue; 
} 
void HandleManager::removeHandle(string hexstring) 
{ 
    this->FreeHandlesAvailable = true; 
    this->FreeHandles.push_front(string_to_hex(hexstring)); 
    this->AssignedHandles--; 
} 

エラーメッセージ:

未処理RVE.exeの0x00C01899の例外:0xC00000FD:スタックオーバーフロー(パラメータ:0x00000001、0x01002F48)。発生しました

パラメータ0x00000001は、ほとんどの場合ハンドルです。メモリアドレスが与えられたオブジェクトを検索する方法はありますか? (0x01002F48)

+4

'std :: auto_ptr'の使用は決して推奨されませんでした。また、C++ 11標準から非難されており、C++ 17標準では削除されています。 –

+0

普通のポインタを使用して、使用後にそれをクリーンアップする必要がありますが、私のエラー –

+1

@YSとやってください。代わりに 'std :: unique_ptr'を使ってください。 – cdhowie

答えて

2

あなたは、ベクターからID3OBJを削除するときに何が起こるかを考えてみましょう:

  1. ベクトルが破壊されますauto_ptr<ID3OBJ> ... ID3OBJ ...
  2. を破壊しようとします
  3. どのデストラクタがベクトルから auto_ptr<ID3OBJ>を削除しようとしますか?
  4. これはauto_ptr<ID3OBJ>を破壊します...そして、我々はステップ1に戻ります。

このプロセスは、スタックがオーバーフローするまで繰り返されます。同じことがVectorベクトルについても当てはまります。 (Roger、Roger。あなたのベクターは何ですか、Victor?)

標準ライブラリvectorは再入可能ではありません。 vectorのメンバーが自分自身を呼び出すと、動作は定義されません。あなたの場合、vector::erase()は間接的に自分自身をデストラクタを通して呼び出します。

したがって、プログラムの動作は未定義です。

+0

動作を説明していただきありがとうございます。後で私の質問にこれを修正する:) –

1

auto_ptr < ..>(これ)、shared_ptr < ..>(これ)またはunique_ptr < ..>(これ)は決して正確ではなく、バグが起こるのを待っています。スマートポインタの値はからのメモリに割り当てられます。はオブジェクトへのポインタであり、どのようになったのかわかりません。あなたは効果的にあなたが達成しようとしているかを理解するのは難しいです

auto_ptr<int> ap(new int); 
auto_ptr<int> ap0(ap.get()); // certain death. 
shared_ptr<int> ap1(ap.get()); // also certain death. 

、以下、

int a; 
auto_ptr<int> ap0(&a); // certain death. 
shared_ptr<int> ap1(&a); // also certain death. 

または均等に悪いような何かをやっています。単にインスタンスを追跡したいのであれば、ベクトルは確実に生ポインタでなければなりません。あなたの目的がメモリ管理であれば、コードからどのように動作するのかわかりません。

+0

私はauto_ptrを使用しています。なぜなら、それはもはや使用されていなければ自動的に解体するので、その中のベクトルのクリーンアップについて心配する必要はありません。ベクトルは、newを使って十分なメモリが利用可能であることを確認するために起動されます;) 新しい生成オブジェクトへのポインタが必要なので 'this'を追加しなければなりません。そして、ポインタは様々な他のオブジェクト。 あなたの例が特定の死につながる理由を教えてください。私の例では、渡す前にオブジェクトを開始するので、次のようになります。 'int a = 5; shared_ptr ap0(&a); ' –

+0

スマートポインタは' delete&a; 'を呼び出すが、'&a'は 'new'を呼び出すことによってメモリが割り当てられないという問題があります。スマートポインタはすべてのポインタを格納するものではなく、ヒープメモリから割り当てられます(つまり、 'new'を使用します)。 –

関連する問題