pthread_key_create 会导致内存泄漏吗?

Does pthread_key_create cause memory leak?

我有一个程序,它有一个 static pthread_key_t key 变量和一个在第一个线程启动时调用 pthread_key_create(&key, &cleanup_function) 的函数。我不想在清理例程中调用 pthread_key_delete,因为它会在线程退出时调用 运行,而不是在所有线程退出时调用。如果另一个线程稍后调用 get_specificset_specific,这将导致问题。 我的问题是:我可以完全省略 pthread_key_delete 吗?当程序最终停止时,这(调用 pthread_key_create 而没有调用 pthread_key_delete )会导致内存泄漏吗?创建pthread_key_t后是否必须调用pthread_key_delete?还是一旦整个问题结束,密钥就进入垃圾收集器或被破坏?

static pthread_key_t key = NULL;

...
static void cleanup(void *value) {
  ...
  if (thread_exit_callback) {
    thread_exit_callback(value);
  }
  free(value);
}

static void *start(void *value) {
  ...
  if (key == NULL){
    pthread_key_create(&key, &cleanup);
  }
  pthread_setspecific(key, value);
  ...
}

程序看起来像这样。

I have a program that has a static pthread_key_t key variable and a function that calls pthread_key_create(&key, &cleanup_function) when the first thread is started.

我猜你是指 第二个 线程,或者第一个通过 pthread_create() 启动的线程 每个进程在启动时都有一个线程。所有执行的代码都在一个线程中执行。

此外,“何时”有点繁琐。最干净的是初始线程创建密钥, 启动任何其他线程之前。否则,您需要进行额外的同步以避免数据竞争。

I don't want to call pthread_key_delete in the cleanup routine because it will run whenever a thread exits instead of when all threads have exited.

文档将您的“清理函数”称为析构函数,我发现该术语更能说明预期目的:不是通用清理,而是线程的适当拆卸-与键关联的特定值。然而,您仍然得出了正确的结论。析构函数(如果给定的话)应该只销毁一个值,而不是键。

Can I just completely leave out pthread_key_delete? Will this (having called pthread_key_create without calling pthread_key_delete afterward) cause any memory leak when the program eventually comes to a halt?

那是未指定的,所以确保调用pthread_key_delete()是最安全的。如果使用密钥的所有线程都是可连接的,那么您可以在加入它们后执行此操作。您也可以考虑注册一个 exit handler 来做到这一点,但显式销毁密钥是更好的方式,可以合理地执行。

话虽如此,如果销毁密钥失败,您不会泄漏任何普通内存,因为当进程退出时,系统会回收属于该进程的所有资源。主要风险是与密钥关联的某些资源的范围会更广,并且它们会泄漏。命名信号量和内存映射文件是此类资源的示例,但我不知道与 TLD 密钥关联的那些特定类型的资源。

does the key just go into the garbage collector or get destructed once the entire problem ends?

C 实现通常不实现垃圾收集,尽管有用于 C 的附加垃圾收集器框架。但是如上所述,属于进程的资源确实会在进程终止时由系统释放。