0

私はinit_segを使用して、3つのC++クラスオブジェクトの作成を制御しています。各オブジェクトは異なるソースファイル/翻訳単位にあります。デバッグでは、CRTの初期化中にオブジェクトが期待どおりに作成されていることが示されます。init_segを使用している場合、3つのC++オブジェクトのセクション/グループに名前を付けるにはどうすればいいですか?

オブジェクトは、ソースファイルのアルファベット順に初期化されています。私はそれが正しくないので、それを変更したいと思います。私はinit_segにMSDNのページを訪問し、それが使用することを述べている:

#pragma init_seg({ compiler | lib | user | "section-name" [, func-name]}) 

それはlibの使用を表示され、section-nameinit_seg(lib)を使用して、セクション/グループ名を提供するためにどのように私にはとてもその明確ではない、相互に排他的ですアルファベット順の順序を取得する。

私は順序を制御するためにアルファベット順に文字列を使用しようとすると:

#pragma init_seg(lib, "01") 

それは私が推測しています警告、その結果は、物事が期待どおりに動作するつもりはありません意味:

warning C4081: expected ')'; found ',' 

".CRT$XCB",".CRT$001"".CRT$XCB001"(アルファベット順を使用する他の変形例)を使用して直接CRTスタートアップコードに直接挿入しようとすると、

私はそれについてのスタックオーバーフローの上に一つの質問を見つけましたが、 answer was a guess、それがカバーしていない

warning C4075: initializers put in unrecognized initialization area 

:それは私が推測しています別の警告、その結果

#pragma init_seg(".CRT$XCB") 

は、物事が期待どおりに動作するつもりはありません意味します複数の翻訳単位。私はまた、KB104248のアーカイブをWayback Machine上に見つけましたが、compiler,libおよびuserの使用しか示されていないため、あまり役に立ちません。

私の質問は、init_segを使って、3つの異なるソースファイルで3つのオブジェクトの正確な作成順序を制御するにはどうすればいいですか?

+0

MSDNのサンプルコードを見ましたか?そのコードに基づいて、あなたが求めていることをどうやってやるのか、合理的な推測をすることはできますが、個人的な経験に基づいて答えを探しているように聞こえるでしょうか? –

+0

ありがとうハリー。どのサンプルコードを参考にしていますか? ['init_priority'](https://msdn.microsoft.com/en-us/library/7977wcck.aspx)ページで提供されているコードを見ましたが、私は' mine $ a'と '.mine $ z'、割り当て、そしてスタートアップコードを置き換えます。標準的なCRTの起動が適切と思われます。私は3つのオブジェクトを特定の順序で挿入する必要があります。 – jww

+0

ドキュメントを正しく読んでいる場合、名前付きセクションを使用すると、CRTは静的オブジェクトを初期化または破棄しないため、コンストラクタとデストラクタを明示的に呼び出す必要があります。その上に、注文を管理することができます。このサンプルコードは、コンパイラ内部の知識を使用して、名前付きセクションにあるオブジェクトのコンストラクタを呼び出すように見えますが、それはあなたのケースでは不要な複雑さだと思います。オブジェクトが何であるかを知っているので、名前で。 –

答えて

2

XPとVS2002/VS2003、VistaとVS2005/VS2008、Windows 7とVS2008/VS2010、Windows 8 VS2010/VS2012/VS2013、およびVS2015を使用するWindows 10 #pragma_init(<name>)はVC++ 1以降で使用可能です。0日。 MSはあまりにも多くの情報を公開していませんが、VC++1.0 (archived KB104248)からVS2017まで記載されています。

  1. #pragma init_seg(lib)はほぼ完璧です。ただし、オブジェクトファイルはVS2008以前ではアルファベット順になっているため、ではなく、a-b-c(不要)となっています。 VS2010以上でOKです。明らかでないことは、ファイルがvcprojのファイルにc-b-aというように正確に配置されていることです。

  2. #pragma init_seg(".CRT$XCB-0NN")と思われます。 std::stringsSTRING_ASTRING_Bは早く作成されましたが、オブジェクトは正しい順序ですが、STRING_Bはsuhutdownでクラッシュしました。アドレスは0x0000000dであり、std::string(およびそのvtable)が早すぎて破棄されたようです。

  3. #pragma init_seg(".CRT$XCU-0NN")は、起動とシャットダウン時に正常に動作しました。私が正しく読んだものを解析した場合、グループ名XCUUはユーザー定義のオブジェクトを示します。つまり、私たちのオブジェクトは、#pragma init_seg(lib)#pragma init_seg(user)の間のどこかに作成されました。だからここ

は、オブジェクトC、その後、オブジェクトB、ソースファイルa.cppb.cppc.cppからオブジェクトAを初期化する方法です。

a.cppソースファイル:

class A 
{ 
    ... 
}; 

#pragma warning(disable: 4075) 
#pragma init_seg(".CRT$XCU-030") 
A a; // created 3rd 
#pragma warning(default: 4075) 

ソースファイルb.cpp

class B 
{ 
    ... 
}; 

#pragma warning(disable: 4075) 
#pragma init_seg(".CRT$XCU-020") 
const B b; // created 2nd 
#pragma warning(default: 4075) 

ソースファイルc.cpp

#pragma warning(disable: 4075) 
#pragma init_seg(".CRT$XCU-010") 
const std::string c; // created 1st 
const std::string d; // created 1st 
#pragma warning(default: 4075) 

私たちのユースケースは、3つの読み取りのみオブジェクトを作成し、C++のstatic initialization order fiascoとMicrosoftのthread local storageの問題を回避することでした。

この手法では、C++ 03でC++の動的初期化子が見つからないようにします。また、マイクロソフトがC++ 11のDynamic Initialization and Destruction with Concurrency(または、より正確には、10年間のコア言語機能を提供できなかったこと)を提供することができません。 Windowsオペレーティング・システムで

Windows Vistaでは、__declspec(スレッド)いくつかの制限があります前に:

はここでMSDNのThread Local Storage (TLS)上の問題への参照です。 DLLがデータまたはオブジェクトを__declspec(スレッド)として宣言すると、動的にロードされると保護違反が発生することがあります。 DLLにLoadLibraryをロードすると、コードが__declspec(スレッド)データを参照するたびにシステム障害が発生します。スレッドのグローバル変数スペースは実行時に割り当てられるため、このスペースのサイズは、アプリケーションの要件と静的にリンクされているすべてのDLLの要件の計算に基づいています。 LoadLibraryを使用する場合、このスペースを拡張して、__declspec(スレッド)で宣言されたスレッドローカル変数を許可することはできません。 LoadLibraryを使用してDLLをロードする場合は、DLL内にTLS API(TlsAllocなど)を使用してTLSを割り当てます。

言及も価値がそのないはセクション名またはグループ名の文字数に制限があるように見えるん。アーカイブされたKB 104248は、名前が"user_defined_segment_name"で26文字です。

+0

指定されたセクション名は、実行可能ファイルのセクションになります。最終的な名前は8文字以下です。長いものは切り捨てられ、余分な文字や$の後の文字は、指定されたセクション内の相対的な順序付けに使用されます。 –

+0

私は[CRTの初期化](https://msdn.microsoft.com/en-us/library/bb918180.aspx)が適切であると考えています.CRTセクションについて説明しています。私は、これがCRTの将来のバージョンで同じアーキテクチャを維持する約束を構成するかどうかは確かではありませんが、少なくとも完全に文書化されていない地域にはありません。 :-) –

+0

スレッドのローカルストレージの関連性がここにあるのかよく分かりません。初期化の順序を制御できるということは、DLLを使う必要がないということですか? –

1

あなたはカスタムセクション名

#pragma section("foo",long,read,write) 
#pragma init_seg("foo") 

を使用する場合は、複数のファイルからのカスタムセグメントは、Aの後に接尾辞を追加することにより、注文されていることを確認することができますセクションの属性を指定する#pragma sectionhttps://msdn.microsoft.com/en-us/library/50bewfwa.aspx)を使用する必要がありますドル記号。 tu1.cppから

// tu1.cpp 
#pragma section("foo$1",long,read,write) 
#pragma init_seg("foo$1") 

// tu2.cpp 
#pragma section("foo$2",long,read,write) 
#pragma init_seg("foo$2") 

データは今tu2.cppから、その前になります

あなたはCRTセグメントにサフィックスを追加することにより、Cランタイムライブラリへの相対的なものを注文することができ

// tu1.cpp 
#pragma section(".CRT$XCU1",long,read,write) 
#pragma init_seg("foo$1") 

// tu2.cpp 
#pragma section(".CRT$XCU2",long,read,write) 
#pragma init_seg("foo$2") 

TU1はTU2の前にあり、他のデータとグループ分けされています。

+0

ありがとうアンソニー。それがどうやって問題を解決するのかはわかりません。 '#pragma init_seg(" foo ")'は、MicrosoftのC++ライブラリの初期化の後、 'crt0.dat'でオブジェクトオブジェクトを作成する前にオブジェクトを配置しますか?また、3つの異なるソースファイルで3つのC++オブジェクトに対してx3を行うにはどうすればよいですか? – jww

+0

私はこれに対処するために私の答えを拡張しました –

関連する問題