包含类的boost :: thread和析构函数

时间:2011-08-29 09:35:13

标签: multithreading boost memory-leaks destructor

我想了解此代码的行为。

class Foo
{
      public:
            Foo();
            ~Foo();
            void run();
            int* get();
    private:
            int *a;
};

Foo::Foo()
{
     a=NULL;       
}
void Foo::run()
{
       if ( a==NULL)
            a = new int[30000];
}

int* Foo::get()
{
    return a;
}

Foo::~Foo()
{
    cout << "destructor called" << endl;
    if ( a!=NULL)
            delete a;
}

int main()
{
        Foo *a = new Foo();

        boost::thread Foothread( &Foo::run, a);
        // Some very long computation that sometimes access 

        int *b  = a->get();
        cout << *b << endl; 
        //Foothread.join();
        //delete a;
        //Foothread.join();

        return 0;
}

此代码导致120000字节的内存泄漏,因为变量a未被破坏,因此当我明确删除它时,泄漏消失,一切都应该没问题。

现在,如果我不是动态分配a,我使用静态分配,多次调用析构函数!!!

int main()
{
        Foo a;

        boost::thread Foothread( &Foo::run, a);
        // Some very long computation that sometimes access "a"
        Foothread.join();
        int *b  = a.get();
        cout << *b << endl; 

        return 0;
}

和输出是     析构函数叫,一个是0     现在a是0     析构函数叫,一个是0     现在a是0     析构函数叫,一个是0     现在a是0     析构函数叫,一个是0     现在a是0     析构函数叫,一个是0     现在a是0     析构函数叫,一个是0     现在a是0     析构函数调用,一个是0x75e300     现在a是0     分段错误

析构函数被称为N次!!

现在我想知道如何使用boost :: thread安全地分配和释放类成员变量和对象,以及为什么线程析构函数不会显式处理类析构函数。

有人可以给我一个暗示吗? boost :: smart_ptr应该帮帮我吗?我必须用malloc分配内存(因为我需要使用一些旧的C API),我怎么能线程安全地做呢?

2 个答案:

答案 0 :(得分:1)

它应该是&amp; a在第二种情况下吗?

boost::thread Foothread( &Foo::run, &a);

答案 1 :(得分:1)

两个版本在线程1中创建类Foo的对象,并从后台线程(线程2)调用其run方法。当run返回时,此后台线程终止。

run实际上初始化了类Foo的对象。您的代码中的一个问题是,您可能会执行一些非常长的计算,有时会在线程1 中完成a的初始化之前在线程1 中访问“a” 。这会导致竞争状况。为避免这种情况,您应在访问Foothread.join()中的Foo::a之前致电a

其他一些观点:

  • 在Foo :: ~Foo()中,您不需要检查要删除的指针是否与NULL不同
  • 必须使用a
  • 删除使用new创建的数组delete[] a;