2011-12-18 13 views
0

ベクトルでC++ 0xイニシャライザリストを使用すると、segフォルトが発生します。私はなぜそれが起こっているのか理解できません。私のデバッガはクラッシュが標準ライブラリにこの機能で起こることを言う:私は、この関数の目的を判断しようとしましたが、私はオンライン任意の説明/ドキュメントを見つけることができませんC++ 0xイニシャライザリストを使用しているときのSegフォルト

template<typename _T1, typename _T2> 
    inline void 
#ifdef __GXX_EXPERIMENTAL_CXX0X__ 
// Allow perfect forwarding 
_Construct(_T1* __p, _T2&& __value) 
#else 
_Construct(_T1* __p, const _T2& __value) 
#endif 
{ 
    // _GLIBCXX_RESOLVE_LIB_DEFECTS 
    // 402. wrong new expression in [some_]allocator::construct 
    ::new(static_cast<void*>(__p)) _T1(_GLIBCXX_FORWARD(_T2, __value)); 
} 

私のコードで初期化リストを使用するコードは次のようになります:

bool Cube::ProcessData(MeshData* data) 
{ 
    data->Clear(); 

    data->v = 
    { 
     Vec3(.5,-.5,-.5), Vec3(.5,-.5,.5), Vec3(-.5,-.5,.5), Vec3(-.5,-.5,-.5), 
     Vec3(.5, .5,-.5), Vec3(.5, .5,.5), Vec3(-.5, .5,.5), Vec3(-.5, .5,-.5) 
    }; 
... 
} 

ここで作成されるこの関数に渡されるデータ構造は:

template <class ProcessorT, class DataT, typename... Args> 
    const DataT* DataManager::RequestData(Args... args) 
    { 
     MutexLock lock(*mutex); 

     Request req; 

     data_cache.PushBack(); 
     req.data  = &data_cache.GetBack(); 
     req.processor = new ProcessorT(args...); 
     request_list.push_back(req); 

     return static_cast<DataT*>(req.data); 
    } 

data_cache構造が私です私がコピーを避けるために使う自分のリストクラス。 ProcessData関数は、データ構造体が作成されたスレッドとは別のスレッドで呼び出されます。

そして、これは、コールスタックのためのデバッガ出力です:

#0 004FAAD6 _Construct<UtilityLib::TVec3<float>, UtilityLib::TVec3<float> const&>(this=0x104aba0, __first=0x593fb98, __last=0x593fbf8) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_construct.h:80) 
#1 00000000 uninitialized_copy<UtilityLib::TVec3<float> const*, UtilityLib::TVec3<float>*>(this=0x104aba0, __first=0x593fb98, __last=0x593fbf8) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_uninitialized.h:74) 
#2 00000000 uninitialized_copy<UtilityLib::TVec3<float> const*, UtilityLib::TVec3<float>*>(this=0x104aba0, __first=0x593fb98, __last=0x593fbf8) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_uninitialized.h:116) 
#3 00000000 __uninitialized_copy_a<UtilityLib::TVec3<float> const*, UtilityLib::TVec3<float>*, UtilityLib::TVec3<float> >(this=0x104aba0, __first=0x593fb98, __last=0x593fbf8) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_uninitialized.h:318) 
#4 00000000 std::vector<UtilityLib::TVec3<float>, std::allocator<UtilityLib::TVec3<float> > >::_M_assign_aux<UtilityLib::TVec3<float> const*>(this=0x104aba0, __first=0x593fb98, __last=0x593fbf8) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/vector.tcc:260) 
#5 004127B3 _M_assign_dispatch<UtilityLib::TVec3<float> const*>(this=0x6e8af18, data=0x104ab98) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_vector.h:1065) 
#6 00000000 assign<UtilityLib::TVec3<float> const*>(this=0x6e8af18, data=0x104ab98) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_vector.h:396) 
#7 00000000 operator=(this=0x6e8af18, data=0x104ab98) (c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_vector.h:359) 
#8 00000000 GameEngine::Render3D::Cube::ProcessData(this=0x6e8af18, data=0x104ab98) (C:\CodeBlocksProjects\GameEngine\src\Primitives.cpp:56) 

私は私のリストクラスが犯人かもしれないが、それであっても、私はなぜ知らないだろうと思われます。うまくいけば、StackOverflowの誰かが私にこの問題を理解させる助けになると思う。私はアドバイスや提案を感謝します。

+0

どのコンパイラ? –

+0

Psst: 'ProcessorT' args:' RequestData(Args && ... args) 'と'新しいProcessorT(std :: forward (args)...); '、' #include 'の完璧な転送を使用してください。 – Xeo

+0

@Ken: "c:/ mingw/bin /../ lib/gcc"はGCCのヒントです。 – Xeo

答えて

0

あなたはconst DataT*としてリターン・RequestDataの種類を指定している間、あなたはProcessData関数に渡しているポインタは、もはや一定ではなく、あなたが指されているオブジェクトを変更ProcessDataのメソッドを呼び出しています。これは、ある関数では定数オブジェクトへのポインタを返すプログラムデザインの根底にある問題を指摘していますが、他の関数やスレッドでポインタの定数の性質を明示的にキャストして、

データの正確性を維持するには、呼び出し元によって変更されるべきではない参照オブジェクトに対してconst T&を返すのが一般的です。外部APIとの互換性を維持しようとしている場合を除き、後で変更可能なオブジェクトにポインタ戻り型を使用してください。 CスタイルのキャストとのC++の後方互換性のために、ポインタタイプを使用するときはconstの保護をキャストするのは非常に簡単です。一方の参照は、オブジェクトの関数呼び出しをfunction-callからfunction-callに維持することよりもはるかに大きなコントロールを提供します。定数参照オブジェクト(または比較的鈍いCスタイルのキャスト)を削除するには、const_castの明示的な操作が必要です.Cスタイルのキャストはポインタオブジェクトの定数を単純に削除することができます以下のようなもの:

const int* test1() { static int a; return &a; } 
void test2(int* a){} 

const int* b = test(); 
test2((int*)b); 

上記ピンポイントあなたのセグメンテーションフォールトのための具体的な理由をしていませんが、私はあなたが定数があなたの基本的な属性を意味としてもともと指定されたメモリを変更しているという事実を信じてやりますdataオブジェクトは変更すべきではなく、スレッドセーフではない可能性があります。したがって、未定義の動作やsegフォルトが発生する可能性があります。

1

最も困難なバグは、通常は最悪です。

問題は、派生クラスではなく、基本クラスにメモリを割り当てていたことでした。私はこのような構造のために新しいと呼ばれる:

class Data 
    { 
    public: 
     enum State { LOADED, UNLOADED, FAILED }; 
     Data(); 
     virtual ~Data(); 
     State state; 
    }; 

私はこの1つのためにメモリを割り当てるされている必要があります場合は:私はMeshDataのインスタンスにアクセスしようとするたびに

struct MeshData : public Data 
    { 
     vector<Vec3> v, n; 
     vector<Vec2> u; 
     vector<Polygon> p; 

     MeshData(); 
     ~MeshData(); 
     void Clear(); 
     string Str()  const; 
     string StrStats() const; 

     bool IsValid() const; 
     bool IsValid(bool& has_n, bool& has_u, bool& all_tri) const; 
}; 

ので、私は境界外のメモリをアクセスしていましたの構造。

私はListクラスが犯人(一種)だと仮定して正しいです。私は割り当てのための型を指定する手段を追加しました:

template <typename TT, typename... Args> void PushBackT(Args... args); 

私はこの問題を手伝ってくれましたみんなに感謝したいと思います。

+1

あなた自身の答えを受け入れて、未解決の質問のリストから削除し、バッジを得る:-)。 –

関連する問題