静态初始化宏是否需要动态清理? (pthread_mutex_initializer 可能需要 pthread_mutex_destroy 吗?)

Can a static initializer macro require dynamic cleanup? (could pthread_mutex_initializer ever require pthread_mutex_destroy?)

我已经查看了许多关于这个主题的其他问题,我觉得我对这个主题有所了解...但是我想讨论这个问题的一个方面。

如此处所述Destroy static mutex and rwlock initializers

(It is not necessary to call pthread_mutex_destroy() on a mutex that was statically initialized using PTHREAD_MUTEX_INITIALIZER.)

但是我想提出一个更基本的问题:

如果一个 API 提供一个宏来初始化一个 object/type,类似于 PTHREAD_MUTEX_INITIALIZER,那么是否有任何宏可以扩展到需要调用一个动态析构函数?

澄清我的问题:

PTHREAD_MUTEX_INITIALIZER 中是否有任何需要动态析构函数进行清理的操作?

如果 object/type 有一个像 PTHREAD_MUTEX_INITIALIZER 这样的静态宏初始值设定项,它 不可能 初始化宏是否可以安全地假设任何需要动态清理的东西,因此 pthread_mutex_destroy 不可能成为 PTHREAD_MUTEX_INITIALIZER?

所必需的

或者是否有可能在将来更改一些可能导致 PTHREAD_MUTEX_INITIALIZER 执行某些绝对需要调用 pthread_mutex_destroy 函数的操作?

编辑:我唯一能想到的可能是注册一个 gcc __attribute__((constructor)) 或其他东西以自动调用一些代码,到那时它就不再是真正的静态初始化了,对吧?如果它确实是静态初始化,那么根据定义 意味着它不能做任何动态的事情;因此 根据定义 静态初始化宏不需要动态清理函数,对吧?

该引用特定于 Linux,并且是 linux 上的事实的结果,pthread_mutex_destroy 本质上是空话。来自手册页:

pthread_mutex_destroy destroys a mutex object, freeing the resources it might hold. The mutex must be unlocked on entrance. In the LinuxThreads implementation, no resources are associated with mutex objects, thus pthread_mutex_destroy actually does nothing except checking that the mutex is unlocked.

因此,在 Linux 上,对于任何互斥锁,都不再需要 pthread_mutex_destroy。

If an API provides a macro to initialize an object/type, similar to the PTHREAD_MUTEX_INITIALIZER, then is there anything that macro could expand out to which would REQUIRE a call to a dynamic destructor function?

总的来说,是的。宏可以扩展为函数调用,或包含一个初始化程序,它可能 return 指向动态分配 space 的指针或包含此类指针的结构或联合。

但对于 PTHREAD_MUTEX_INITIALIZER 或任何其他可用于初始化文件范围变量的宏,不。这样的初始化器必须由常量表达式构造,并且这样的初始化器不能包含任何需要清理的东西。

但是请注意,这不是一个完整的故事。无论对象是如何初始化的,其后续使用都会有无数种方式导致需要通过析构函数释放资源以遵守它。特别是,POSIX 不保证未能销毁通过宏初始化的互斥体不会有任何后果。它也没有在通过初始化宏初始化的互斥锁的初始状态和通过 pthread_mutex_init() 初始化的具有默认属性的互斥锁的初始状态之间做出任何区分。无论哪种方式,需要清理的资源都可以通过调用 pthread_mutex_lock() 与此类互斥体相关联。例如。

但不要忽视,这个领域的任何"requirement"都是有条件的,不是绝对的。可能需要调用 pthread_mutex_destroy() 以便 实现理想的结果,例如避免资源泄漏。不打电话意味着获得不同的结果,这可能仍然是可以接受的。

也许 NULL 宏就是一个很好的例子。任何指针对象都可以用 NULL 初始化,这不具有任何资源管理含义。但是,如果随后将指向动态分配的 space 的指针分配给它,那么未能将该对象的值传递给 free() 可能会导致资源泄漏。然而这样的泄漏可能是可以接受的——例如,如果分配的 space 无论如何都需要保留到程序终止,那么程序是自己释放它还是依赖于 OS 将其作为流程后清理的一部分进行处理。