使用boost :: timed_join和FreeLibrary时崩溃

时间:2012-09-18 00:11:07

标签: c++ dll segmentation-fault boost-thread hang

我需要使用LoadLibraryGetProcAddress来调用某些dll(插入我的应用程序)中的函数,但我不希望它们能够挂起我的程序无限循环或悬挂自己,所以我试图用boost::thread(没有经验)来规避这一点。但是,如果某个函数挂起,则在调用FreeLibrary进行清理时,会因ACCESS_DENIED(0x00000005)而崩溃。

这是一个重现问题的最小DLL(mydll.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();行,但这产生了相同的结果。

我也试过以下无济于事:

  • 用函数替换lambda(我不确定Boost适合C ++ 11的东西)---崩溃
  • 评论FreeLibrary行---工作正常,但是在加载之后我宁愿释放它,即使它是基于参考的。我对后来的这种行为也持谨慎态度。
  • 用返回的一个替换DLL中的无限循环---工作正常,但我不能指望
  • 不使用LoadLibrary或任何内容并内联无限循环---工作正常,但我需要使用DLL:
  

boost :: thread thr = [] {for(;;);};

DLL和cpp都是在Windows 7 64位上使用GCC 4.7.1和32位输出类型编译的。我的Boost版本是1.49.0。如果内存服务,我想在移动到另一台计算机之前,我在Windows XP 32位(相同的编译器等)上进行了一两次测试。

为什么会崩溃?如何确保我动态调用的函数不会挂起我的程序?

1 个答案:

答案 0 :(得分:2)

从根本上说,你不能这样做。线程不提供这种隔离。如果需要,请使用流程。