使用C++11的线程库和boehm-gc

3
我们知道,在多线程中使用boehm-gc需要调用GC_register_my_thread,并将栈基地址从GC_get_stack_base传递过来。但是似乎不适用于C++11的线程库,例如std::thread... 我该如何在C++11的线程库中使用boehm-gc?
(我使用VS2013)
编辑:这是经过测试的代码。std::thread很好用,但是std::future无法正常工作(停留在_CrtIsValidHeapPointer)。
#include <iostream>
#include <thread>
#include <future>

#define GC_THREADS
#include <gc.h>
#include <gc_cpp.h>
#pragma comment(lib, "gcmt-lib")

void foo()
{
    GC_stack_base sb;
    GC_get_stack_base(&sb);
    GC_register_my_thread(&sb);

    int *ptr;
    for (int i = 0; i < 10; i++)
    {
        ptr = new (GC) int;
        *ptr = 1;
    }

    GC_unregister_my_thread();
}

int main()
{
    GC_INIT();
    GC_allow_register_threads();

    std::cout << "test for std::thread";
    std::thread thrd(foo);
    thrd.join();
    std::cout << " [sucs]\n";

    std::cout << "test for std::future";
    std::future<void> fu = std::async(std::launch::async, foo);
    fu.get();
    std::cout << " [sucs]\n";

    std::cin.get();
}

编辑:这是一个堆栈跟踪的截图(抱歉它不是英语,但我认为这并不重要)

在此输入图片描述

以下是一个调试信息

HEAP[TestGC.exe]: Invalid address specified to RtlValidateHeap( 00E80000, 00C92F80 )

在调试过程中,我发现错误发生在fu.get()之后。

编辑:使用/MD(或/MDd)时不会出现错误...

(我认为垃圾回收可能会触及库的指针(命名空间并发),但这只是猜测;;)

1个回答

2
在使用收集器和创建线程之前,请确保发出以下两个命令:GC_INITGC_allow_register_threads。然后在每个线程中跟进,使用GC_get_stack_base/GC_register_my_thread,最后使用GC_unregister_my_thread。虽然你没有说明你正在使用什么编译器,但它适用于gcc 4.8(带有-std=c++11)。编辑:OP通过解决上述指示并使用多线程动态MSVCR100运行时的/MD[d]标志编译代码来解决了该问题。对于多线程静态编译运行时,该问题仍未解决。

1
规范中并没有保证 std::async 会在单独的线程上运行。如果你想强制这样做,你必须运行 std::async(std::launch::async, foo); - mockinterface
我再次使用std::launch::async进行了测试,但是仍然出现了相同的错误; - ikh
你可能需要添加_CrtIsValidHeapPointer失败的堆栈跟踪。顺便问一下,如果您在主函数中注释掉线程测试,是否会发生这种情况? - mockinterface
你是否偶然指定了GC_win32_dll_threads定义?gcmt-lib是如何构建的? 总体而言,看起来收集器正在拦截内部并发对象(MS c++11 lib实现细节)的创建,因此它被删除了两次。但我需要在装有msvc编译器的计算机上进行检查。 - mockinterface
请务必检查 GC_ 方法的返回值,例如,GC_register_my_thread() 是否返回了 GC_SUCCESS - mockinterface
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接