1

次のような原因不明の動作が発生しました。

ケース1:

a.cpp.dllライブラリとしてコンパイルされ、のmain()で使用されます。main.cpp

Bar b; 

//constr
Bar::Bar(){
  //... initialize members
}

//private library init
Bar::init(){ ...}

//public API init
bool lib_init(){
  b.init();
}

私が理解していることから、このアプローチは、グローバルの未定義の初期化動作が原因で失敗する可能性があります。

ケース2:

a.cpp.dllライブラリとしてコンパイルされ、のmain()で使用されます。main.cpp

Bar* b; 

//constr
Bar::Bar(){
  //... initialize members
}

//private library init
Bar::init(){ ...}

//public API init
bool lib_init(){
  b = new Bar;
  b->init();
}

今回は、動的割り当てを使用すると機能します。

ケース3(最も驚くべき)

a.cpp.dllライブラリとしてコンパイルされ、のmain()で使用されます。main.cpp

static Bar& getBarObj()
{
  static Bar g_objBar;
  return g_objBar;
}

//constr
Bar::Bar(){
  //... initialize members
}

//private library init
Bar::init(){ ...}

//public API init
bool lib_init(){
  getBarObj().init();
}

Bar objのインスタンス化が定義されていない可能性があるケース1とは対照的に、ケース3では「要求に応じて」使用されます。ただし、ケース3はケース1と同じ動作を提供します。

そして私の質問は...誰かがここで何が起こっているのか説明できますか?すべてがVC2008リリースモードで構築されています(このプロジェクトのデバッグモードのオプションはありません)

4

2 に答える 2

0

異なるファイルからのグローバルの初期化の順序(あなたが間違いなく持っている場合)は、C++では定義されていません。これは、別のコンパイル単位でのグローバル初期化中に構築されたことに依存しBar bている場合、プログラムは未定義であることを意味します。

ケース3が機能することになっている理由は、参照する関数を使用する必要があり、この関数がこの関数が戻るまでに作成されているBar bことを保証するためです。Bar b

発生している正確な未定義の動作を教えてください。また、分析するコードの量を最小限に抑えれば、さらに支援できる可能性があります。

PSコンストラクターは、Bar構築された別のグローバルに依存していますか?

于 2012-04-30T06:56:46.177 に答える
0

の構築は本質的にリンク順序に任されているため、ケース 1 は失敗する可能性がありbます (これは C++ 仕様によって制御されていません。C++ の未定義の動作ですが、動作はリンカーによって定義できます!) いずれの場合でも、一度呼び出すと、同じモジュールに存在し、離れてlib_init b構築されることが許可されています。lib_initb

ケース 3 は、必要なときに b を構成し、他のすべての静的およびグローバル オブジェクトと逆の順序で構成され、終了時にそれを破棄します。Bar::Bar()これは、呼び出しが内部にfoo_init()static を持っている場合、古いコンパイラで問題を引き起こす可能性があります。この事実は、2003 仕様以降、発生するはずです。構築完了後に破棄スケジューリングを行う必要がありました (そのため、ctor は ctor の前に完了するため、終了時に dtor の前に bar dtor が呼び出されます。FooBarBarFooBarFooFooBarFooBarFoo

ケース 2 は「醜い」: ケース 3 (オンデマンドで作成) のように構築で動作しますが、2 つの問題があります。

  • lib_init() と ...
  • 誰がバーを破壊しますか? Os は終了時にメモリを解放しますが、dtor は呼び出されません。

ケース 2 は、おそらく次のように定義したほうがよいでしょう。

void lib_init()
{
    static std::unique_ptr<Bar> p(new Bar);
    p->init();
}

しかし、これはケース3のようになります。

于 2012-04-30T07:24:29.340 に答える