简体   繁体   English

pthread_key_create 会导致内存泄漏吗?

[英]Does pthread_key_create cause memory leak?

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.我有一个程序,它有一个static pthread_key_t key变量和一个在第一个线程启动时调用pthread_key_create(&key, &cleanup_function)的函数。 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.我不想在清理例程中调用pthread_key_delete ,因为它会在线程退出时运行,而不是在所有线程都退出时运行。 This will cause problems if another thread calls get_specific or set_specific later on.如果另一个线程稍后调用get_specificset_specific这将导致问题。 My question is: Can I just completely leave out pthread_key_delete ?我的问题是:我可以完全省略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_create而不调用pthread_key_delete )会导致任何内存泄漏吗? Is it mandatory to call pthread_key_delete after creating a pthread_key_t?创建pthread_key_delete后是否必须调用 pthread_key_delete? Or does the key just go into the garbage collector or get destructed once the entire problem ends?或者密钥是直接进入垃圾收集器还是在整个问题结束后被破坏?

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);
  ...
}

The program looks something like this.该程序看起来像这样。

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.我有一个程序,它有一个static pthread_key_t key变量和一个在第一个线程启动时调用pthread_key_create(&key, &cleanup_function)的函数。

I presume you mean the second thread, or the first started via pthread_create() Every process has one thread at startup.我想你的意思是第二个线程,或者第一个通过pthread_create()启动的每个进程在启动时都有一个线程。 All code that is executed is executed in a thread.执行的所有代码都在一个线程中执行。

Also, "when" is a bit fiddly.此外,“何时”有点繁琐。 It is cleanest for the initial thread to create the key, and that before launching any other threads.启动任何其他线程之前,初始线程创建密钥是最干净的。 Otherwise, you need to engage additional synchronization to avoid a data race.否则,您需要进行额外的同步以避免数据竞争。

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.我不想在清理例程中调用pthread_key_delete ,因为它会在线程退出时运行,而不是在所有线程都退出时运行。

The documentation refers to your "cleanup function" as a destructor , which term I find to be more indicative of the intended purpose: not generic cleanup, but appropriate teardown for thread-specific values associated with the key.该文档将您的“清理函数”称为析构函数,我发现该术语更能说明预期目的:不是通用清理,而是与键关联的线程特定值的适当拆卸。 You have nevertheless come to the right conclusion, however.不过,您还是得出了正确的结论。 The destructor function, if given, should tear down only a value, not the key.析构函数,如果给定,应该只删除一个值,而不是键。

Can I just completely leave out pthread_key_delete ?我可以完全省略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_create而不调用pthread_key_delete )会导致任何内存泄漏吗?

That is unspecified, so it is safest to ensure that pthread_key_delete() is called.这是未指定的,因此确保调用pthread_key_delete()是最安全的。 If all threads using the key are joinable then you can do that after joining them.如果使用该键的所有线程都是可连接的,那么您可以在加入它们后执行此操作。 You could also consider registering an exit handler to do that, but explicitly destroying the key is better style where that can reasonably be performed.您也可以考虑注册一个退出处理程序来做到这一点,但在可以合理执行的情况下,显式销毁密钥是更好的风格。

With that said, you will not leak any ordinary memory if you fail to destroy the key, as the system will reclaim all resources belonging to a process when that process exits.话虽如此,如果您未能销毁密钥,您将不会泄漏任何普通内存,因为当该进程退出时,系统将回收属于该进程的所有资源。 The main risk is that some of the resources associated with the key will be more broadly scoped, and that they would leak.主要风险是与密钥相关的一些资源的范围更广,并且它们会泄漏。 Named semaphores and memory-mapped files are examples of such resources, though I have no knowledge of those specific types of resources being associated with TLD keys.命名信号量和内存映射文件是此类资源的示例,尽管我不知道与 TLD 密钥关联的那些特定类型的资源。

does the key just go into the garbage collector or get destructed once the entire problem ends?一旦整个问题结束,密钥是直接进入垃圾收集器还是被破坏?

C implementations do not typically implement garbage collection, though there are add-in garbage collector frameworks for C. But as described above, the resources belonging to a process do get released by the system when the process terminates. C 实现通常不实现垃圾收集,尽管有 C 的附加垃圾收集器框架。但如上所述,属于进程的资源确实会在进程终止时由系统释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM