5

要約:今日、プリコンパイル済みヘッダーなしでDLLをビルドすると、使用しようとすると奇妙なエラーが表示されることを発見しました。

プリコンパイル済みヘッダーが無効になっている場合、DLLの構築は正常に行われます。ただし、DLLが(コンパイル時または実行時に)接続されるとすぐに、「無効なパラメータ」というエラーが発生します。実際のエラーコードは、どちらの場合も異なります。コンパイル時をアタッチすると、ダイアログがエラーコード0xc000000dでポップアップし、呼び出すLoadLibrary()NULLポインタをGetLastError()返し、0x57を返します。

編集:

インクリメンタルリンクを無効にすると、問題が解決することを発見しました。どういうわけか、DLLコンパイル時に接続するクライアントを実行しているときにVisualStudioによって表示される次のエラーを見逃しました。

'TestClient.exe': Loaded 'D:\Projects\PchDllTest2\Debug\TestClient.exe', Symbols loaded.
'TestClient.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll', Cannot find or open the PDB file
'TestClient.exe': Loaded 'C:\WINDOWS\system32\kernel32.dll', Cannot find or open the PDB file
'TestClient.exe': Loaded 'D:\Projects\PchDllTest2\Debug\TestDll.dll', Symbols loaded.
SXS: RtlCreateActivationContext() failed 0xc000000d
LDR: LdrpWalkImportDescriptor() failed to probe D:\Projects\PchDllTest2\Debug\TestDll.dll for its manifest, ntstatus 0xc000000d
Debugger:: An unhandled non-continuable exception was thrown during process load
The program '[5292] TestClient.exe: Native' has exited with code -1073741811 (0xc000000d).

要求に応じて、関数宣言:

#ifdef __cplusplus
extern "C" {
#endif

MYTEST_API int MyTestFoo(int a);

#ifdef __cplusplus
}
#endif

これについて注目すべき点が1つあります。ウィザードを使用して新しいDLLを作成する場合([新しいプロジェクト]-> [Visual C ++]-> [Win32]-> [Win32プロジェクト])、ウィザードは、アプリケーションタイプとしてDLLを選択するときに、プリコンパイル済みヘッダーを使用するように強制します。ta.speot.isからの回答を参照してください。

DLLプロジェクトにはPCHが必要であることが何らかの形で文書化されていると最初に思ったように見えたので、質問を大幅に変更しました。これはそうではありません、それはおそらく奇妙な種類のバグです(そうでないことを願っています)またはおそらく私は非常に愚かなことをしています...

4

3 に答える 3

6

DLLを構築するときにプリコンパイル済みヘッダーが必要なのはなぜですか?

彼らはそうではありません。

要約:今日、私は、プリコンパイル済みヘッダーを使用して構築せずに(機能する)DLLを作成することはできないことを発見しました。誰かがこれの理由が何であるか知っていますか?

これを発見する理由は、あなたが何かを読み間違えたからです。

プリコンパイル済みヘッダーなしでバイナリを作成できます。

これについて注目すべき点が1つあります。ウィザードを使用して新しいDLLを作成する場合([新しいプロジェクト]-> [Visual C ++]-> [Win32]-> [Win32プロジェクト])、ウィザードは、アプリケーションタイプとしてDLLを選択するときに、プリコンパイル済みヘッダーを使用するように強制します。

おそらくVisualC++ 6ですが、VisualStudioでの私の経験はそうではないことを示唆しています。ウィザードを使用して空のプロジェクトを作成すると、プリコンパイル済みヘッダーは取得されません。

ウィザード

それはさておき、私はグーグルで「そのマニフェスト、ntstatus 0xc000000d」を探し、最終的にここに行き着きました。最後の答えは、CRTのバージョンが一致していないことを示しています。これは、Visual Studioにプロジェクトを作成させ、デフォルトのままにしておくと、非常に困難になります。

「ホスト」アプリケーションとライブラリで同じバージョンのCRTにリンクしていることを確認するのにお金がかかる場合があります(たとえば、両方ともマルチスレッドデバッグです)。

私が考えることができる他の唯一のことは、付随するファイル(ファイルがある場合)なしでフォルダーに移動TestDll.dllしているということです。DebugTestDll.dll.manifest

于 2012-08-27T08:40:13.760 に答える
4

DLLには、リトルエンディアンのUTF-16バイトオーダーマークのみを含むマニフェストリソースが埋め込まれていることがわかりました。Windows DLLローダーは、そのようなDLLを読み込もうとすると、説明されているエラーでクラッシュします。

これは奇妙なバグだと私は確信しています。VisualStudioまたはMSBuildを使用してDLLをビルドすると、偽のマニフェストリソースを含むDLLが作成されます。MSBuildによって報告されたコマンドをコマンドラインで手動で実行すると、DLLにはUTF-8BOMを持つ有効なマニフェストリソースが含まれています。

  • 説明したように、PCHを無効にしてDLLを構築すると、UTF-16LEBOMのみを含むマニフェストリソースが生成されます。
  • DLLがPCHを有効にして構築されている場合、マニフェストリソースにはUTF-8BOMとそれに続く有効なXMLが含まれます。
  • DLLがPCHを無効にし、インクリメンタルリンクを無効にして構築されている場合、マニフェストリソースにはXMLのみが含まれ、BOMはまったく含まれません。

もう1つのオプションは、ビルドの完了後にリソースエディターを使用して障害のあるマニフェストリソースを削除することです。エラーも消えます。

これは、ウィザードを使用するか、空のプロジェクトを作成してすべてを自分で行う場合に、非常に再現性があります。

于 2012-08-28T12:15:22.280 に答える
0

「プリコンパイル済み」ヘッダーを使用すると、以前にコンパイルされたコードを効果的に使用できます。後でバグを導入した場合、「プリコンパイル」はバグをコンパイルしませんが、古いバグのないコードを使用します。

于 2012-08-27T08:38:37.130 に答える