【问题标题】:Memory leaks when using pthead_exit() to exit thread使用 pthead_exit() 退出线程时内存泄漏
【发布时间】:2013-06-28 16:29:11
【问题描述】:

使用pthread_exit()退出时出现问题。我的代码是这样的:

{
    ...
    pthread_attr_t attr;
    iRetValue = pthread_attr_init(&attr);
    iRetValue = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    size_t nStackSize = 4 * 1024 * 1024;
    iRetValue = pthread_attr_setstacksize(&attr, nStackSize);
    while(condition)
    {
        ...
        int32 iSockId = cServSocket.accept();
        if(iSockId < 0)
        {
             continue;
        }  
        pthread_t tid;
        int32* pSockId = new int(iSockId);
        iRetValue = pthread_create(&tid, &attr, run_thread, (void*)pSockId);
        ...
    }
    ...
    pthread_attr_destroy(&attr);
}

void* run_thread(void* p)
{
    int32 iSockId = *(int32*)p;
    if(p != NULL){delete p}
    int32 iRetValue = g_dealMgr.deal_thread(iSockId);

    return (void*)iRetValue;
}
int32 CDealMgr::deal_thread(int32 iSocket)
{
    ...   // many temporarydata create,expect will release autoly
    pthread_exit((void*)1);
    return 0;
} 

实际上,它会导致内存泄漏,当我将pthread_exit((void*)1);移动到run_thread时,就像这样

void* run_thread(void* p)
{
    int32 iSockId = *(int32*)p;
    if(p != NULL){delete p}
    int32 iRetValue = g_dealMgr.deal_thread(iSockId);
    pthread_exit((void*)1);
    return (void*)iRetValue;
}
int32 CDealMgr::deal_thread(int32 iSocket)
{
    ...   // many temporary data create,expect will release autoly
    return 0;
}

内存泄漏消失。 现在,我的问题是,为什么在调用run_thread()的函数中使用pthread_exit()会导致内存泄漏,希望有人能帮助我,非常感谢。

【问题讨论】:

  • 您需要向我们展示更多...也许deal_thread 在到达pthread_exit 之前返回
  • 日志显示在pthread_exit之前没有返回,一直到pthread_exit,我可以保证。
  • 你是否从父线程完成了thread_join()?
  • @rakib 他正在使用PTHREAD_CREATE_DETACHED 创建线程,所以他不需要加入。

标签: c++ memory-leaks pthreads exit


【解决方案1】:

问题在于,在 C++ 中,return 会导致堆栈展开并破坏局部变量。调用pthread_exit() 只能保证调用注册到pthread_cancel_push() 的取消处理程序。您需要从deal_thread 正常返回,以确保在其堆栈上声明的所有变量都被正确销毁。

一旦你调用pthread_exit,线程就会停止运行——它不会从deal_thread返回(甚至不会继续执行它)。你不需要显式调用pthread_exit,当你从run_thread返回时也会发生同样的事情。

这个:

void* run_thread(void* p)
{
    pthread_exit((void*)1);
}

等价于:

void* run_thread(void* p)
{
    return (void*)1;
}

查看关于implicit call to pthread_exit()here的段落。

另请注意,如果您使用NULL 调用它,run_thread 可能会崩溃。您应该将前 2 行更改为:

int32 iSockId = 0;
if (p != NULL) {
    iSockId = *(int32*)p;
    delete p;
}

【讨论】:

  • 谢谢你的回答,你的意思是deal_thread或run_thread中的pthread_exit有同样的结果?但是我的测试表明deal_thread中的pthread_exit会导致内存泄漏,而run_thread中的pthread_exit不会......
  • 是的,它们是等价的。您如何测试内存泄漏?
  • 这个程序是一个服务,当客户端连接时,创建一个run_thread。我使用测试箱每1ms发送一次请求,然后内存迅速上升,即使我停止测试箱也不会减少。
  • 每个请求都是在新连接上发出的?
  • 问题不太可能来自pthread_exit()。您必须显示来自run_threaddeal_thread 的更多代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-29
  • 2013-12-18
  • 2015-10-05
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
相关资源
最近更新 更多