2

我有一个应用程序在主线程中使用pthread_create()和,稍后在子线程中使用。pthread_detach()pthread_exit()

经过大约 54 个pthread_create()呼叫,每个呼叫都与后续呼叫配对,然后pthread_detach()失败。这是失败的“内存不足”。pthread_exit()pthread_create()ENOMEM

什么可能导致pthread_exit()无法释放旧线程的内存并导致我的应用程序泄漏内存并最终耗尽?

这是在 Linux Centos 5 64 位但 32 位构建的应用程序上运行的。

这是创建同时调用pthread_create()和的线程的代码pthread_detach()

int
_createThread()
{
  pthread_attr_t attr;
  int return_val;

  return_val = setupMutex(_Mtx());

  if (return_val != 0) {
    return return_val;
  }

  return_val = setupCond(_StartCond());

  if (return_val != 0) {
    return return_val;
  }

  return_val = setupCond(_EndCond());

  if (return_val != 0) {
    return return_val;
  }

  return_val = pthread_attr_init(&attr);

  if (return_val != 0) {
    return -1;
  }

  size_t stackSize = 1024 * 1024 * 64; // Our default stack size 64MB.

  return_val = pthread_attr_setstacksize(&attr, stackSize);

  if (return_val != 0) {
    return -1;
  }

  int tries = 0;

 retry:
  // _initialize() gets called by the thread once it is created.
  return_val = pthread_create(&_threadId, &attr,
                              (void *(*)(void *))_initialize,
                              (void *)this);

  if (return_val != 0) {
    if (return_val == EAGAIN) {
      if (++tries < 10) {
        Exit::deferredWarning(Exit::eagainThread);
        goto retry;
      }
    }
    return -1;
  }

  return_val = pthread_attr_destroy(&attr);

  if (return_val != 0) {
    return -1;
  }

  return_val = pthread_detach(_threadId);

  if (return_val != 0) {
    return -1;
  }

  // Wait for the new thread to finish starting up.
  return_val = waitOnCond(_Mtx(), _EndCond(), &_endCount, 10 /* timeout */, 0,
                          "_createThread-end");

  if (return_val != 0) {
    return -1;
  }

  return 0;
}

void
_exitThread()
{
  (void) releaseCond(_Mtx(), _EndCond(), &_endCount, "_exitThread-end");
  pthread_exit(NULL);
}
4

4 回答 4

4

在pthread_exit之前调用pthread_join以便线程可以在退出之前进行清理。

于 2010-12-25T16:34:49.053 回答
2

解释在pthread_create的手册页中:

当一个分离的线程终止时,它的资源会自动释放回系统,而不需要另一个线程加入终止的线程

因此,如果您既不分离也不加入它,您就会失去一些资源,最终提高 ENOMEM。

您应该分离线程或将其从其父线程加入。

于 2016-08-25T08:00:47.123 回答
1

威尔,我已经删除了我的旧答案,因为我似乎弄错了。沿着这条线,我有一个问题:你是怎么得到的ENOMEM?您是否按照我在回答中指出的那样检查了“errno”?因为pthread_create是规则的例外,并且没有设置errno;相反,错误会作为结果返回。

获取失败原因的正确方法:

int err = pthread_create(...);
if(err)
{
    perror( "Error creating thread" );
    printf( "Error: %s\n", strerror( err ) );
    return false;
}

我问的原因是因为pthread_createENOMEM 永远不会失败!如果没有内存,pthread_create将返回EAGAIN。有关 EAGAIN 与 ENOMEM 的信息,请参阅http://sourceware.org/ml/glibc-bugs/2007-11/msg00007.html

编辑

明显的问题:系统确实有足够的可用内存,对吗?

于 2010-12-28T15:45:56.247 回答
0

如果加入不适用于您的用例,请致电pthread_join()或替代。pthread_detatch()

发生此错误是因为库正在存储所有终止线程的退出代码,等待通过pthread_join(). 或者,如果您不关心线程的退出代码,请pthread_detatch()在创建后调用。这告诉 API 你不关心它的返回码,所以它不需要存储它。

于 2016-02-15T04:53:42.443 回答