pthread_join 是否释放被终止线程占用的堆?

does pthread_join free the heap that is held by the terminated thread?

我正在看一本教科书,上面写着:

int pthread_join(pthread_t tid, void **thread_return);

The pthread_join function blocks until thread tid terminates, assigns the generic (void *) pointer returned by the thread routine to the location pointed to by thread_return, and then reaps any memory resources held by the terminated thread.

我对终止线程持有的内存资源有点困惑,听起来 pthread_join 会隐式调用 free 来释放终止线程中的堆内存,但很明显这是不正确的,例如:

void *thread(void *arg) {
  char *ret;

  if ((ret = (char*) malloc(20)) == NULL) {       //<------------allocated heap memory
    perror("malloc() error");
    exit(2);
  }
  strcpy(ret, "This is a test");
  pthread_exit(ret);
}

main() {
  pthread_t thid;
  void *ret;

  if (pthread_create(&thid, NULL, thread, NULL) != 0) {
    perror("pthread_create() error");
    exit(1);
  }

  if (pthread_join(thid, &ret) != 0) {          
    perror("pthread_create() error");
    exit(3);
  }

  printf("thread exited with '%s'\n", ret);
}

调用pthread_join后,ret仍然指向分配的堆内存,可以打印字符串。所以对等线程中分配的堆内存还没有释放。

那么被终止的线程持有什么样的内存资源会被回收?

创建线程;通常某个地方的东西(例如可能是库,可能是内核)需要为新线程分配一个堆栈,当它不使用 CPU 时创建某个地方来存储它的状态(寄存器等),创建某个地方来存储 meta-data(信号掩码、优先级、CPU 使用时间等),为其线程本地存储分配 space 等。所有这些都需要释放;但它们是您的代码不负责的“内部内容”(库需要负责)。

你能控制的东西(堆内存)大部分属于进程,不属于任何特定的线程;并且不会在任何线程终止时释放(除非最后一个线程终止导致进程终止,因为它没有剩余线程)。