LoadLibrary()で問題が発生し、意味のないエラーが発生します。
::SetLastError(0);
m_hDll = ::LoadLibrary(szName);
if (m_hDll == NULL) // Failure to load the DLL.
{
DWORD err = GetLastError();
}
エラーは127です(「指定されたプロシージャが見つかりませんでした。」)LoadLibrary()の呼び出しでは意味がありません。まだGetProcaddress()を呼び出していません。
DLL(およびアプリケーション)は両方ともVS ++ 2005SP1でコンパイルされます。
何がうまくいかない可能性がありますか?
これを段階的に見ていきましょう。
エラーメッセージは、dllが見つかりましたが、必要な機能がないことを意味します。 (ジッターは正しいです。)これは、必要なdllがあるが、正しいバージョンではないことを意味します。 (Davefiddesは正しいですが、問題はMicrosoftランタイムライブラリだけでなく、任意のdllである可能性があります。また、少なくともメジャーアップデートの場合、Microsoftはランタイムライブラリに異なる名前を付けるため、その場合は問題になりません。)
ロードされているdllから関数が要求されていないため、これは意味がありません。 (アダムは正しいです。)
したがって、不足している関数は、LoadLibraryコマンドによって明示的にロードされているdllではなく、最初のdllが必要とするため、同時に暗黙的にロードされている依存dllで見つかると予想されていました。 (ゼブラボックスは近かった。)
依存dllは、明示的にロードされたdllのリンカステップに含まれるインポートライブラリまたは.libファイルを介して、明示的にロードされているライブラリに「静的に」リンクされているdllです。 (「ダイナミックリンクライブラリ」が「静的にリンク」できることを知らなかったに違いありません。まあ、今はそうです。)
異なるフォルダに同じdllの複数のバージョンがある場合、これは検索パスの問題である可能性もあります(zebraboxが示唆しているように)。 DLLパスの検索順序は、それ自体が複雑なテーマです。 http://msdn.Microsoft.com/en-us/library/ms682586(VS.85).aspx を参照してください。とりわけ、オペレーティングシステムによって異なります。最も安全な方法は、実用的な場合、潜在的な問題のあるすべてのdllをexeファイルと同じフォルダーに配置することです。
依存dllは、独自の依存dllを持つこともできるため、この問題の解決が非常に困難になる可能性があります。依存することは役立つかもしれませんが、そうでない場合は、filemonを試してください。エラーメッセージの前に正常に読み取られた最後のdllは、バージョンが間違っているdllです。
Microsoft gflags ツールは、どの依存関係がロードに失敗しているのか、そしてその理由を常に正確に教えてくれます。
_gflags -i your_application.exe +sls
_を実行します。その後、デバッガーでアプリケーションを実行して ローダートレース をキャプチャします。
gflagsは Debugging Tools の一部です-C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
をチェックインして、すでに持っているかどうかを確認できます。そのディレクトリをパスに追加するか、cmd.exeでそのディレクトリからgflagsを実行することができます。
たとえば、gflagsを実行した後、::LoadLibrary(_T("foo"))
呼び出しにブレークポイントを設定し、VisualStudio出力ウィンドウでローダーエラーを探しながらそれをステップオーバーします。
_4b00:396c @ 479194074 - LdrpSnapThunk - ERROR: Procedure "?SetObject@vis_DollarMap@@QEAAXHPEAX@Z" could not be located in DLL "bar.dll"
First-chance exception at 0x0000000077307EF8 (ntdll.dll) in your_application.exe: 0xC0000139: Entry Point Not Found.
4b00:396c @ 479194074 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapIAT raised exception 0xc0000139
Exception record: .exr 0000000000129070
Context record: .cxr 0000000000128B80
4b00:396c @ 479194074 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Snapping the imports from DLL "C:\test\64Debug\foo.DLL" to DLL "C:\test\64Debug\bar.dll" failed with status 0xc0000139
_
これは、_foo.dll
_のロード中に、依存関係_bar.dll
_がインポートされ、_bar.dll
_のインポートが失敗したことを意味します。
プロシージャ_?SetObject@vis_DollarMap@@QEAAXHPEAX@Z
_が欠落しているため、依存関係のインポートに失敗しました-public: void __cdecl vis_DollarMap::SetObject(int,void * __ptr64) __ptr64
に demangle することができます。
依存関係のバージョンが間違っている可能性があります。依存関係を再構築して最新の状態にする必要があるかもしれません。
その後、_gflags -i your_application.exe -sls
_を実行して、ローダートレースを無効にします。
エラーメッセージは、適切なDLLが見つかりましたが、必要なプロシージャのエクスポートがありません。正しいバージョンのDLLがありますか?
dumpbin.exe
を使用して、DLLがエクスポートする関数を確認し、スペルを確認できます。
デバッガーツールをインストールし、gflags -i your_application.exe +sls
を実行します。その後、デバッガーでアプリケーションを実行して、ローダーのトレースをキャプチャします。
アプリとDLLに使用されるランタイムの間に不一致がありますか?
過去にVS2005で私を悩ませてきた問題は、一方の部分がリリースビルドとしてビルドされ、もう一方がデバッグビルドとしてビルドされることです。これらは、特定のプロセスでロードできるのは1つだけであるため、互換性のない異なるバージョンのMicrosoftランタイムDLLを取り込みます。
エラー127が表示される理由は、DLLがロードされたランタイムで関数を探しているためだと思いますDLL間違っているため、そこにはありませんランタイム。
私からの2つの推測
1。 LoadLibraryは、指定されたDLL(初めてプロセスに接続しようとしたとき)のDllMainを呼び出します。ロングショットですが、そこにありますか?
2。 LoadLibraryは、指定されたDLLとそのすべての依存関係をロードします。したがって、DLLの依存モジュールが検索パスに見つからない場合、ロードが失敗する-depends.exeを使用して確認できます-利用可能 ここ
Dependency Walker を使用して、欠落しているメソッド、または必要なDLLまたは欠落しているDLLを見つけることをお勧めします。
LoadLibrary()を呼び出した後、同じエラーコードが表示されていました。最後に、依存関係ウォーカーを通じて、モジュール(szName)のいくつかの依存関係が欠落していることがわかりました。
わかりました、これが私の解決策です:複雑な依存関係システムがあり、その中に同じ名前(つまり、server.dll
)の2つのDLLがありましたが、異なるパスにありました。
client.dll
にLOAD_WITH_ALTERED_SEARCH_PATH
がロードされたとき、Windowsはシンボル解決でserver.dll
のどちらを使用すべきかを判断できなかったようです(両方のserver.dll
は正常に実行されました)もちろん、ロードされます)。
解決策は非常に簡単でした。ロードされたdllに一意の名前、つまりserver-1.dll
とserver-2.dll
を付けます。