【问题标题】:pthread_create: cannot allocate memorypthread_create:无法分配内存
【发布时间】:2017-07-15 13:00:57
【问题描述】:

我写了一个小型 tcp 服务器,它为每个传入的连接创建一个新线程:

while (server_running)
{
  client_sock = accept(server_sock,
                   (struct sockaddr *)&client_name,
                   &client_name_len);

  if(!server_running)
    break;
  if (client_sock == -1)
    continue;
  /* accept_request(client_sock); */
  if (pthread_create(&newthread , NULL, &accept_request, &client_sock) != 0)
    perror("pthread_create");
}

大约 380 次成功连接后,错误信息

'pthread_create: 无法分配内存'

在每次新的连接尝试时发生。我真的不知道这是从哪里来的,因为accept_request 运行正常。我还注意到在运行期间有许多状态为TIME_WAIT 的连接(我为此使用了netstat)。那么哪里出了问题呢?

【问题讨论】:

  • minimal reproducible example,尽管从您发布的内容来看,这看起来并不好。
  • 你曾经关闭连接并结束线程吗?两者都是有限的资源,看来你正在达到线程的限制......
  • 可能你最后没有释放线程的资源。您必须分离线程或加入它,以便线程使用的所有内存在他退出后被释放。在您的情况下,最好创建从一开始就分离的线程。
  • 我在 accept_request 结束时关闭了 client_sock
  • @user2224350 当然可以,但是你处理线程了吗?即使您退出/返回线程,线程也会消耗大量资源,直到您从其他地方调用线程上的 pthread_join(),或者如果线程分离,它会自动处置。默认情况下,llinux 上的线程有 8 或 10 MB 的堆栈内存。所以 380 个线程意味着你使用了将近 4GB 的虚拟内存——这可能意味着你达到了限制。

标签: c linux sockets pthreads


【解决方案1】:

当你的线程退出时,它仍然在内存中徘徊。默认情况下,Linux 上的一个线程消耗 8 或 10MB 的堆栈,因此使用 380 个线程,您可能会使用近 4GB 的虚拟内存——这可能会达到系统的限制。

要在执行完线程后将其释放,您需要在该线程上调用pthread_join(),或者您可以使该线程成为“分离”线程。一个分离的线程将在它结束执行时自动被释放。你可以添加

pthread_detach(pthread_self());

accept_request() 线程函数的开头,使其成为分离线程。

附带说明,您在调用

时存在竞争条件
 pthread_create(&newthread , NULL, &accept_request, &client_sock)

在这里,您将 &client_sock 传递给线程,这是一个局部变量。如果您有 2 个客户端几乎同时连接到您的服务器,最后一个将覆盖 client_sock 变量,并且您的 2 个线程将看到相同的文件描述符。你可以例如而是这样做:

int *new_fd = malloc(sizeof *new_fd);
*new_fd = client_sock;
pthread_create(&newthread , NULL, &accept_request, new_fd)

并确保您的 accept_request 线程 free() 是传入的参数。

【讨论】:

    猜你喜欢
    • 2017-11-18
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    • 2011-09-18
    • 2015-05-17
    • 2015-08-15
    • 2015-04-01
    • 2017-12-05
    相关资源
    最近更新 更多