LoadLibrary
一部のdll(アプリにプラグインする)を使用して関数を呼び出す必要がありますGetProcAddress
が、無限ループを含めたり自分自身をハングさせたりしてプログラムをハングさせたくないので、使用しようとしていますboost::thread
(経験なし)それを回避するために。ただし、関数がハングした場合、FreeLibrary
クリーンアップを呼び出すときに ACCESS_DENIED (0x00000005) でクラッシュします。
mydll.dll
問題を再現する最小限の DLL ( ) を次に示します。
extern "C" {
void __declspec(dllexport) foo() {
for(;;); //<-- infinite loop
}
}
そして、これがクラッシュする最小限の cpp です。簡潔にするためにエラーチェックを省略しましたが、エラーが発生しないことを保証できます。
#include <boost/thread.hpp>
#include <iostream>
#include <windows.h>
int main() {
using FuncType = void (*)();
HMODULE dll = LoadLibrary("mydll.dll");
FuncType func = (FuncType)GetProcAddress(dll, "foo");
boost::thread thr = [func] {func();};
if (!thr.timed_join(boost::posix_time::seconds(1))) {
std::cout << "Timed out.";
//thr.detach();
FreeLibrary(dll);
}
for (;;);
}
これを実行すると、「タイムアウトしました。」が出力され、クラッシュ時のコール スタック (CodeBlocks の gdb) は次のようになります。
#0 00000000 0x6c1c1214 in ??() (??:??)
#1 0040133E operator() (__closure=<optimized out>) (C:\...\thread test.cpp:17)
#5 00000000 0x00000000 in ??() (??:??)
最適化を行わないと、次のようになります。
#0 00000000 0x6c1c1214 in ??() (??:??)
#1 00401348 operator() (__closure=0x898f90) (C:\...\thread test.cpp:17)
#2 00401780 boost::detail::thread_data<main()::<lambda()> >::run(void)(this=0x898f70) (c:/.../boost/thread/detail/thread.hpp:62)
#5 00000000 0x00000000 in ??() (??:??)
最初に試したのは、thr.detach();
上でコメントアウトした行を追加することでしたが、同じ結果が得られました。
また、次のことを試してみましたが、役に立ちませんでした。
- ラムダを関数に置き換える (Boost が C++11 のものにどれだけ適合するかはわかりません) --- クラッシュします
- 行 --- をコメントアウトする
FreeLibrary
と問題なく動作しますが、参照ベースであっても、ロード後に解放したいと思います。私はまた、この種の動作が後で機能することにも注意を払っています。 - DLL の無限ループを --- を返すものに置き換えると問題なく動作しますが、それを期待することはできません
- または何も使用せず
LoadLibrary
、無限ループをインライン化 --- 正常に動作しますが、DLL を使用する必要があります。
ブースト::スレッド thr = []{for (;;);};
DLL と cpp は両方とも、32 ビット出力タイプの GCC 4.7.1 を使用して Windows 7 64 ビットでコンパイルされました。Boost の私のバージョンは 1.49.0 です。メモリが機能する場合、別のコンピューターに移動する前に、Windows XP 32 ビット (同じコンパイラーなど) で 1 つまたは 2 つのテストを行ったと思います。
なぜこれがクラッシュするのですか?動的に呼び出す関数がプログラムをハングさせないようにするにはどうすればよいですか?