首頁  >  問答  >  主體

多线程 - C++11 std::thread这么使用为什么不对?

我写了这么一段代码,是想用B包裹一个线程,然后方便做一些操作,和关联一些变量。

class B
{
public:
    B(std::thread* a):t(a)
    {}
    static void run(B* s)
    {
        while(s->done)
        {
            //do something
        }
    }
private:
    bool done/*=false*/;
    std::thread* t;
};
class A
{
    A():
    a(new std::thread(&B::run,&a)),
    b(new std::thread(&B::run,&b)),
    c(new std::thread(&B::run,&c)),
    d(new std::thread(&B::run,&d))
    {}
private:
    B a;
    B b;
    B c;
    B d;
};

然后在VS2015下就出事了,函数B::run()传入的参数指针s的内容都是0xcdcdcdcd。但是看了一下,参数s的地址和申请时候的地址却是一样的,在主线程也查了一下这个地址发现却是有内容的,请问这是怎么回事呢?
或者说我的使用方法有误?正确的方法是什么样子的呢?

============

原本的问题是这样的,我有一个程序要在一个阶段要产生大量的片元数据来进行类似的插值计算,这些计算原本是在单线程的,后来发现消耗太高想把这些任务分给几个线程,让这些线程来完成这些任务,最后把结果合并起来。
我想的是给每个线程都搞了一个单生产者单消费者队列,主线程不断地根据负载把片元往这些线程里面装,线程不断消化,然后在一个指定的地方同步。
大概代码是这样的:
上面那个B是我用来包裹线程的类,我的思路是把队列和一些其他和这个线程相关的操作(同步、写入计算数据,写入计算终结信号等等)都封装到一起,然后程序开始的时候创建四个B对象,让这四个线程都跑起来,然后主线程可以调用B的方法不断地往线程中写入数据,最后可以使用同步操作来同步四个线程和主线程。
B::run就是我的执行函数。A类相当于是主线程初始化的类。

PHP中文网PHP中文网2764 天前989

全部回覆(5)我來回復

  • 怪我咯

    怪我咯2017-04-17 13:28:48

    因為在建構子中傳遞了this指標

    回覆
    0
  • 迷茫

    迷茫2017-04-17 13:28:48

    測試了你的程式碼,沒有問題。
    我也是覺得你創建出來的A物件有可能析構了。 。 。
    看你發出來的程式碼不是原始碼吧。 A的建構子都是私有的
    還有就是記得new了記憶體 用完了要delete掉

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:28:48

    你的主執行緒是不是沒有呼叫子執行緒的join函數,這樣主執行緒可能會先於子執行緒完成。然後子線程還在跑,主線程就已經呼叫了相關類別的析構函數了?

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 13:28:48

    你是怎麼查看的s的值?

    而且a(new std::thread(&B::run,&a))這種寫法本身就有問題吧,B::run(&a)的呼叫可能在a的成員被建構之前,同時B: :run(&a)用到了a.done。

    可以試試

    class B {
        public:
            B(): done(false), t([this](){run();}) {}
            void run() {while (done) /*do something*/;}
        private:
            bool done;
            std::thread t;
    };
    class A {
        private:
            B a, b, c, d;
    };

    回覆
    0
  • 阿神

    阿神2017-04-17 13:28:48

    https://en.wikipedia.org/wiki/Magic_number_%28programming%29
    這是debug版本的CRT為了方便調試程序,在分配出來還沒有初始化的時候提供的初始值。

    實際上,Windows上面還有更多這樣的初始值,請見下表:

    Uninitialized:
    BAADF00D Used by Microsoft's LocalAlloc/GlobalAlloc/HeapAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
    CCCCCCCC Used CDCbed Cun​​ykm DCDCD Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory

    Freed:

    FEEEFEEE Used by Microsoft's LocalFree/GlobalFree/HeapFree() to mark freed heap memory
    DDDDDDDD Used by MicroQuill's SmartHeap and Microsofts C++ debugging he 到 bugging
    No man's land:

    ABABABAB Used by Microsoft's LocalAlloc/GlobalAlloc/HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory

    FDdnosed FDFDs POK FDb; " guard bytes before and after allocated heap memory

    回覆
    0
  • 取消回覆