2017-10-06 14 views
2

私は枝で構成されるツリーを作成しています。私の仕事の目的のために、私は枝を追跡する必要があり、それを行うために、私はベクトルリストにそれらを保存したい。以下のコードスニペットに示すコンストラクタと関数の両方で使用したいので、このファイルにグローバル変数としてベクトルリストを格納します。ベクトルリストをグローバル変数として保存するにはどうしたらいいですか?

ここで難しいのは、私が知る限り、イテレータが適切に仕事をしていないことがあるというエラーメッセージ(Visual Studio 2013で実行中)が表示されることです。エラーメッセージは、branchList.push_back(root)とbranchList.resize()を呼び出すたびに表示されます。 branchList.size()はエラーにはなりません。

私の質問は次のとおりです。この仕事をするために何が欠けているのか理解していないのですか?私はベクトルbranchListを配置する場合は、コンストラクタの冒頭で、すべてが意図どおりに機能します。しかしこれは後で他の関数でも使う必要があるので、私には役に立ちません。

私が使用しているファイルの関連するスニペット。

skeletonBuilder.h:

class TreeSkeleton { 

public: 
    TreeSkeleton(); 
    void growTree(); 
}; 

skeletonBuilder.cpp:

#include "skeletonBuilder.h" 
#include <cstdint> 
#include <vector> 


typedef struct branch { 
    branch *parent; 
    vec3 position; 
    vec3 direction; 
} branch; 

//used by constructor + "treeGrow" function 
std::vector<branch> branchList = {}; 

TreeSkeleton::TreeSkeleton() { 
    //instantiate the tree root as a starting position. 
    branch root; 
    root.parent = NULL; 
    root.position = vec3(0, 0, 0); 
    root.direction = vec3(0, 1, 0); 

    branchList.size(); //works fine 
    branchList.resize(100); //Crashes here 
    branchList.push_back(root); //Crashes here 
} 

TreeSkeleton::growTree() { 
    //pushing more branches to branchList 
} 

main.cppに:

#include "skeletonBuilder.h" 

TreeSkeleton tree; 

int main(int argc, char *argv[]) { 

    return 0; 
} 

私は取得していますエラーメッセージ:

Unhandled exception at 0x00507077 in OpenGL_project_Debug.exe: 0xC0000005: Access violation reading location 0x40EAAAB4. 

エラーメッセージは「ベクター」というファイルに次のコードスニペットに私を取る:

#if _VECTOR_ORPHAN_RANGE 
void _Orphan_range(pointer _First, pointer _Last) const 
    { // orphan iterators within specified (inclusive) range 
    _Lockit _Lock(_LOCK_DEBUG); 
    const_iterator **_Pnext = (const_iterator **)this->_Getpfirst(); 
    if (_Pnext != 0) 
     while (*_Pnext != 0) //<----------------This is the row that it gets stuck on 
      if ((*_Pnext)->_Ptr < _First || _Last < (*_Pnext)->_Ptr) 
       _Pnext = (const_iterator **)(*_Pnext)->_Getpnext(); 
      else 
       { // orphan the iterator 
       (*_Pnext)->_Clrcont(); 
       *_Pnext = *(const_iterator **)(*_Pnext)->_Getpnext(); 
       } 
    } 
+0

あなたは完全にグローバルを排除することですさらに良い – UnholySheep

答えて

1

グローバルオブジェクトの初期化順序は実装ファイル間で保証されません。最初にmain.cppまたはskeletonBuilder.cppのグローバルが最初に初期化されることはわかりません。あなたの場合、はstd::vector<branch> branchListの前に初期化され、問題が発生します。 TreeSkeletonのコンストラクタは未定義の動作である初期化されていないbranchListを使用する必要があります。解決策は、の順番がであるようにグローバルを配置することです。

解決策の1つは、ローカル静的変数branchListにすることです。これらの変数は、最初に遭遇したときに初期化されることが保証されています。例えば

class TreeSkeleton { 

public: 
    TreeSkeleton(); 
    void growTree(); 

private: 
    static std::vector<branch> & getBranches(); 
}; 

std::vector<branch> & TreeSkeleton::getBranches() 
{ 
    // branchList is initialized the first time this line is encountered 
    static std::vector<branch> branchList; 
    return branchList; 
} 

TreeSkeleton::TreeSkeleton() 
{ 
    //instantiate the tree root as a starting position. 
    branch root; 
    root.parent = NULL; 
    root.position = vec3(0, 0, 0); 
    root.direction = vec3(0, 1, 0); 

    auto & branchList = getBranches(); 
    branchList.size(); 
    branchList.push_back(root); // Should be fine now 
} 
+0

を取得している*正確な*エラーメッセージをコピー&ペーストしてください。私は、これらの変数が、ツリー内に含まれるベクトル(メンバーとして、またはすべてのツリー間で共有される場合は静的)とメイン関数内で宣言されるツリーではなく、グローバルにする必要はないと考えています。 –

+0

さて、私があなたが言っていることを理解し、あなたが書いた機能を使用しようとします。しかし、1つの問題は、structブランチが.cppファイルに実装されていることです。つまり、 "static std :: vector ..."は "ブランチ"が何であるかわかりません。 –

+0

必要がある場合は、実装ファイルで静的メンバー関数をフリー関数に変更できます。 –

関連する問題