【问题标题】:multithread segment fault destructors多线程段错误析构函数
【发布时间】:2022-01-03 19:03:58
【问题描述】:

我调用unit_thread_data函数时出现段错误,其实是~Data()引起的。 thread1 是可以的,但是 thread2 导致了段错误,整个代码是休闲的:(原谅糟糕的代码风格),错误信息是双重释放或损坏。其他信息:gcc5.4.0,centos7。有什么帮助吗?非常感谢!

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
class Data
{
public:
    int* A_;
    Data()
    {
        cout<<"111\n";
        A_=NULL;
    }
    ~Data()
    {
        cout<<"222\n";
        if(A_) {
            delete A_;
        }
    }
};

struct thread_data_t
{
    Data* d;
};

void* _add(void* _pthread_data)
{
    thread_data_t* pthread_data = (thread_data_t*) _pthread_data;
    pthread_data->d->A_ = new int[2];
    pthread_data->d->A_[0] = 1;
    pthread_data->d->A_[1] = 2;
    std::cout<<pthread_data->d->A_[0]+pthread_data->d->A_[1]<<endl;
    return (void*)0;
}

void unit_thread_data(thread_data_t* pthread_data)
{
    for(int i=0;i<2;i++)
    {
        delete[] pthread_data[i].d->A_;
        delete pthread_data[i].d;
    }
    delete[] pthread_data;
}
int main()
{
    int num_threads = 2;
    pthread_t threads[num_threads];
    thread_data_t* pthread_data = new thread_data_t[num_threads];
    for(int i=0;i<num_threads; i++)
    {
        pthread_data[i].d = new Data();
    }
    for (int i=0; i<num_threads; i++) {
        pthread_create(&threads[i], NULL, _add, (void*)(pthread_data+i));
    }
    for (int i=0; i<num_threads; i++) {
        pthread_join(threads[i], NULL);
    }
    sleep(1);
    unit_thread_data(pthread_data);
    return 0;
}

【问题讨论】:

  • 删除delete[] pthread_data[i].d-&gt;A_;A_Data的析构函数删除。
  • 建议:如果您使用的是 C++11 或更高版本,请使用标准的 std::thread 类,而不是平台特定的 C API pthread
  • 这并没有解决问题,但是您不需要在析构函数中测试A_ 是否为空。 delete A_; 可以处理空指针。
  • @Pete Becker:谢谢Pete,我学会了

标签: c++ pthreads destructor segment


【解决方案1】:
delete[] pthread_data[i].d->A_;

这会删除Data 类的A_ 成员int *

紧接着,就会发生这种情况:

delete pthread_data[i].d;

这会删除Data 本身。 Data 的析构函数然后执行以下操作:

    if(A_) {
        delete A_;
    }

然后继续尝试delete 相同的指针。这首先应该是delete[]d 而不是deleted,但这没有实际意义,因为这个指针已经是deleted,它会第二次尝试delete

这会导致未定义的行为。

【讨论】:

  • 是的!我明白了,谢谢山姆 :)
【解决方案2】:

是因为你先在这里删除成员A_

delete[] pthread_data[i].d->A_;

之后没有将nullptr 分配给A_,然后在析构函数中调用delete A_;

除此之外,在您的代码中,不清楚谁应该是在A_(函数_addunit_thread_data,或类本身)下分配的内存的所有者,因此很容易做到这一点各种错误。

快速修复(不推荐):只需移除析构函数的主体,让外部函数_addunit_thread_data 管理内存。

更好的解决方法(推荐):考虑谁应该是分配数据的所有者(我会说class Data)并尽可能使用std::unique_ptr

【讨论】:

    【解决方案3】:

    删除A_后需要赋值NULL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-22
      • 2012-11-19
      • 2012-02-05
      • 2018-09-24
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多