3

私は、VC8 (VS2005) でビルドおよびテストされた非常に大規模で複雑なプロジェクト (実際には、119 の「プロジェクト」で構成される「ソリューション」であり、そのほとんどが DLL) を継承しており、それを VC9 に移植するタスクがあります。 (VS2008)。

私が使用した移植プロセスは次のとおりです。

  1. VC8 .sln ファイルをコピーし、名前を VC9 .sln ファイルに変更します。
  2. すべての VC8 プロジェクト ファイルをコピーし、名前を VC9 プロジェクト ファイルに変更します。
  3. すべての VC9 プロジェクト ファイル、s/vc8/vc9 を編集します。
  4. VC9 .sln、s/vc8/vc9/ を編集します。
  5. VS2008 で VC9 .sln をロードし、IDE にすべてのプロジェクト ファイルを「変換」させます。
  6. 適切なビルドが得られるまで、コンパイラとリンカーのエラーを修正します。

これまでのところ、最後のステップで次の問題に遭遇しました。

1) 装飾された名前の計算方法が変更され、名前が切り捨てられました。

これは単なる警告ではありません ( http://msdn.microsoft.com/en-us/library/074af4b6.aspx )。この警告でビルドされたライブラリは、他のモジュールとリンクしません。MSDN に記載されている解決策を適用することは簡単ではありませんが、実行可能でした。この問題については、「VC9 (MSVC 2008) で許可されている修飾名の長さを増やすにはどうすればよいですか?」で個別に対処しました。

2) イテレータにゼロを代入できない変更。これは仕様によるものであり、以前は許可されていたこれらのコーディング エラーを見つけて修正するのはかなり簡単でした。イテレータにゼロを代入する代わりに、値 end() を使用します。

3) for ループのスコープは、ANSI 標準に準拠するようになりました。別の簡単に修正できる問題。

4) プリコンパイル済みヘッダーに必要なスペースが増えます。場合によっては、さらに多くのスペースが必要でした。/Zm999 を使用して最大の PCH スペースを提供することになりました。PCH のメモリ使用量が再び増加した場合は、PCH を完全に使用せずに、ビルド時間の増加に耐える必要があると思います。

5) コピー ctor およびデフォルト dtor の要件の変更。テンプレート クラスでは、特定の条件下で、まだよくわかっていませんが、コンパイラはデフォルトの ctor またはデフォルトの dtor を生成しなくなったようです。これは VC9 のバグだと思いますが、他に何か間違っている可能性があります。もしそうなら、それが何であるかを知りたいです。

6) sln および vcproj ファイルの GUID は変更されませんでした。これは、私が検出できる方法でビルドに影響を与えるようには見えませんが、それでも心配です.

これらすべての問題にもかかわらず、プロジェクトは VC8 でビルド、実行、広範な QA テストに合格したことに注意してください。また、すべての変更を VC8 プロジェクトにバックポートしましたが、以前と同じように (VS2005/VC8 を使用して) ビルドして実行することができます。したがって、VC9 ビルドに必要なすべての変更は、少なくとも下位互換性があるように見えますが、回帰テストはまだ進行中です。

ここで、非常に難しい問題について説明します。VC8 プロジェクトと VC9 プロジェクトの起動シーケンスの違いに遭遇しました。このプログラムは、Andrei Alexandrescu の Book Modern C++ Designで、Loki をモデルにした小さなオブジェクト アロケーターを使用します。このアロケータは、メイン プログラム モジュールで定義されたグローバル変数を使用して初期化されます。

VC8 では、このグローバル変数はプログラム起動の最初に、モジュール crtexe.c のコードから構築されます。VC9 では、最初に実行されるモジュールは crtdll.c で、これは起動シーケンスが変更されたことを示します。起動中の DLL は、グローバル オブジェクトが統計を初期化する前にメモリの割り当てと割り当て解除を行うことで、スモール オブジェクト アロケータを混乱させているように見えます。これにより、誤った診断が行われます。プログラムの動作は実質的に影響を受けていないようですが、QA 担当者は偽の診断がそれらを通り抜けることを許可しません。

DLL をロードする前に、グローバル オブジェクトの構築を強制する方法はありますか?

他にどのような移植の問題が発生する可能性がありますか?

4

5 に答える 5

1

これは難しい問題です。これは主に、グローバル変数の初期化順序に依存することが想定されていないため、本質的に危険な設計を継承しているためです。

グローバル変数を、シングルトンオブジェクトへのポインタを返すグローバル関数またはメソッドを呼び出すことによって他の関数が取得するシングルトンに置き換えることで、回避しようとすることができるように思えます。呼び出し時にオブジェクトが存在する場合、関数はそのオブジェクトへのポインターを返します。それ以外の場合は、新しいオブジェクトを割り当て、新しく割り当てられたオブジェクトへのポインタを返します。

もちろん、問題は、あなたが説明している問題を回避するシングルトン実装を考えることができないということです。たぶん、この議論は役に立つでしょう:http ://www.oneunified.net/blog/Personal/SoftwareDevelopment/CPP/Singleton.article

于 2009-02-04T20:37:16.573 に答える
1

DLL をロードする前に、グローバル オブジェクトの構築を強制する方法はありますか?

DELAYLOAD オプションはどうですか? 最初の呼び出しまで DLL が読み込まれないようにするためですか?

于 2009-02-03T20:22:01.890 に答える
0

この問題の解決策は、私が当初考えていたよりも簡単であることがわかりました。初期化順序の問題は、stdコンテナタイプから派生したタイプのグローバル変数がいくつか存在することが原因で発生しました(その会社での私の立場よりも前の基本的な設計上の欠陥)。解決策は、そのようなすべてのグローバルをシングルトンに置き換えることでした。それらの約100がありました。

これが行われると、初期化(および破棄)の順序はプログラマーの制御下に置かれました。

于 2012-03-28T20:07:06.973 に答える
0

それは確かに興味深い問題です。おそらく設計を変更して、注文またはリンク/dllの起動の未定義の動作に依存しないようにする以外に解決策はありません。古いリンカーとのリンクを検討しましたか? (またはVS.NET用語が何であれ)

変数とアロケータの動作は、(当時は不明な) 任意の起動順序に依存していたため、今後問題にならないように修正する予定です。問題を解消するためにVC9でブードゥー教を行う方法を誰かが知っているかどうかを本当に尋ねていると思います。私も興味深く聞いています。

于 2008-10-31T20:30:38.167 に答える
0

これはどう、

  1. メイン プログラムも DLL にして、それを main.dll と呼び、他のすべてのものにリンクし、メイン関数を mainEntry() としてエクスポートします。グローバル変数を削除します。
  2. グローバル変数とその初期化を持つが、他のアプリケーション DLL のいずれにも静的にリンクしない新しいメイン exe を作成します (アロケーターのものを除く)。
  3. 次に、この新しい main.exe は、LoadLibrary() を使用して main.dll を動的にロードし、GetProcAddress を使用して mainEntry() を呼び出します。
于 2009-02-03T23:37:14.167 に答える