2

読者は、マネージ コードとアンマネージ コードが混在するシステムと、それらが必要な理由に精通していることを前提としています。この質問では、それについては扱いませんが、Visual Studio 2008 コンパイラとリンカー コントロールを使用してこのようなシステムを構築するメカニズムについて説明します。

背景

まず、もみ殻を取り除きます。私の調査では、次のことがわかります。

  • 初期の C++ プロジェクトは MFC ベース
  • 共有 dll の MFC
  • クリアなし
  • C++ 例外 /EHa
  • マルチスレッド デバッグ /MD

これはすべて、Visual Studio 2008 のすべての開発者ワークステーションで正しくビルドおよび実行されます。

現在、サード パーティの C# .NET3.5 SP1 ライブラリがプロジェクトに含まれています。このライブラリは、相互運用のためにネイティブ C++ ブリッジを使用して構築されています。元の C++ プロジェクトは、この新しいライブラリのインポート ファイルをリンカー入力の一部として参照します。すべてかなり標準的なもので、フォーラムでよく参照されています。

サードパーティ ライブラリは次のように構築されます。

  • 共通言語ランタイムのサポート /clr
  • C++ 例外 /EHa
  • マルチスレッド デバッグ /MD

問題

8 つの開発者ワークステーションで、デバッグ (およびリリース) ビルドはすべて正しくビルドおよび起動されます。開発者ワークステーションの 1 つだけが、起動時に次のエラーを受け取ります。

Windows が blah.exe でブレークポイントをトリガーしました。
これは、ヒープの破損が原因である可能性があります。これは、blah.exe または読み込まれた DLL のバグを示しています。

これはアプリケーションの起動前に発生するため、追跡が困難です。私は以下を使用/試行/削除しました:

  • 正しく構成されていないワークステーション。そうは言っても、まったく同じワークステーションは 2 つとありません。はい、それらはすべて同じツールとオペレーティング システム (Windows-7) を使用していますが、それ以上は構成が若干異なります。
  • 依存ウォーカー
  • プロセス分析ツール (ProcMon)
  • 静的ライブラリのビルドが互いに一致していないため、ヒープの不一致が発生します。コンパイラ スイッチ /MD は、両方のコードベースに対応しています。つまり、CLR のヒープは常にネイティブ コードのヒープとは異なります。

ソリューション

C++ ビルドの/clrをオンにすると、すべての問題が解消されます。なんで?両方のコード空間が同じヒープを使用するようになると思います。確かに異なるランタイム環境が混合モードのすべてですか? これは推奨されるソリューションではありません。

最新情報

Visual Studio のデバッグ ウィンドウには、次のように表示されます。

*「blah.exe」でアクセス違反が発生しました:

747220A3 の命令が、無効なアドレス 00000B90 から読み取ろうとしました。

  • 例外レコードに .exr 00032690 を入力します
  • コンテキストに .cxr 000326AC を入力します
  • 次に kb で障害スタックを取得します

blah.exe の 0x747220a3 (MSCTF.dll) での初回例外: 0xC0000005: アクセス違反の読み取り場所 0x00000b90。

付録

C++ プロジェクト コンパイラ オプション (デバッグ ビルド):

/Od /D "WIN32" /D "_WINDOWS" /D "_D​​EBUG" /D "_VC80_UPGRADE=0x0710" /D "_AFXDLL" /D "_MBCS" /FD /EHa /MDd /Yu"stdafx.h" /Fp" Debug\blah.pch" /Fo"Debug\" /Fd"Debug\vc90.pdb" /W3 /WX /nologo /c /Zi /clr /TP /wd4793 /wd4996 /errorReport:prompt

C++ プロジェクト リンカー オプション (デバッグ ビルド):

/OUT:"..\Debug\blah.exe" /INCREMENTAL /NOLOGO /MANIFEST /MANIFESTFILE:"Debug\blah.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /ASSEMBLYDEBUG /PDB:"blah.pdb" /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE /DYNAMICBASE:NO /FIXED:いいえ /MACHINE:X86 /ERRORREPORT:PROMPT iphlpapi.lib UxTheme.lib ../Libraries/Bridge.lib

C# .NET ライブラリ コンパイラ オプション (デバッグ ビルド):

/Od /D "WIN32" /D "_D​​EBUG" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /FD /EHa /MDd /Yu"stdafx.h" /Fp"Debug\Bridge.pch" / Fo"Debug\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /Zi /clr /TP /errorReport:prompt /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System. dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll" /FU "Library.dll"

C# .NET ライブラリ リンカー オプション (デバッグ ビルド):

/OUT:"Bridge.dll" /INCREMENTAL /NOLOGO /DLL /MANIFEST /MANIFESTFILE:"Debug\Bridge.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /ASSEMBLYDEBUG / PDB:"Bridge.pdb" /DYNAMICBASE /FIXED:いいえ /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT

4

1 に答える 1

1

この問題は、問題の DLL に DELAY LOAD を適用するだけで解決されました。これにより、起動時の負荷が軽減され、起動時の競合が回避されたとしか思えません。

DLL は、機能が最初に使用されたときにいつでも読み込まれます。すべてのワークステーションで正しく動作します。

于 2012-07-19T11:25:20.650 に答える