【问题标题】:Can a static initializer macro require dynamic cleanup? (could pthread_mutex_initializer ever require pthread_mutex_destroy?)静态初始化器宏是否需要动态清理? (pthread_mutex_initializer 可能需要 pthread_mutex_destroy 吗?)
【发布时间】:2019-09-03 19:58:48
【问题描述】:

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

如此处所述Destroy static mutex and rwlock initializers

(不必在使用 PTHREAD_MUTEX_INITIALIZER 静态初始化的互斥体上调用 pthread_mutex_destroy()。)

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

如果 API 提供了用于初始化对象/类型的宏,类似于 PTHREAD_MUTEX_INITIALIZER,那么该宏是否可以扩展为需要调用动态析构函数的任何内容?

澄清我在问什么:

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

是否可以安全地假设,如果一个对象/类型有一个像 PTHREAD_MUTEX_INITIALIZER 这样的静态宏初始化器,那么宏不可能初始化任何需要动态清理的东西,因此pthread_mutex_destroy 不可能成为 PTHREAD_MUTEX_INITIALIZER 的必要条件?

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

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

【问题讨论】:

  • 它可以在首次使用时动态分配资源。如果失败,它可以退回到轮询。例如CRITICAL_SECTION 可以在需要时动态分配内部事件。理论上,实现可以在销毁函数中释放此类事件。
  • 好点我从未考虑过首次使用场景

标签: c pthreads mutex


【解决方案1】:

如果 API 提供了一个宏来初始化一个对象/类型,类似于 PTHREAD_MUTEX_INITIALIZER,那么有什么宏可以 展开到需要调用动态析构函数的地方 功能?

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

但对于PTHREAD_MUTEX_INITIALIZER 或任何其他可用于初始化文件范围变量的宏,不。这样的初始化程序必须由常量表达式构造,并且这样的初始化程序不能包含任何强制清理的内容。

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

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

NULL 宏可能就是一个很好的例子。任何指针对象都可以使用NULL 进行初始化,这对资源管理没有任何影响。但是,如果随后将指向动态分配空间的指针分配给它,则未能将该对象的值传递给free() 可能会导致资源泄漏。然而,这样的泄漏可能是可以接受的——例如,如果分配的空间无论如何都需要保留到程序终止,那么程序是否自行释放它,或者它是否依赖操作系统来处理它,这几乎没有什么实际区别。处理后的清理。

【讨论】:

    【解决方案2】:

    该引用是特定于 Linux 的,并且是由于在 linux 上,pthread_mutex_destroy 本质上是一个 noop 的事实。从手册页:

    pthread_mutex_destroy 销毁一个互斥对象,释放它可能持有的资源。这 互斥锁必须在入口处解锁。在 LinuxThreads 实现中,没有资源 与互斥对象相关联,因此 pthread_mutex_destroy 实际上什么都不做,除了 检查互斥锁是否已解锁。

    因此在 Linux 上,对于任何互斥体,pthread_mutex_destroy 都不是必需的。

    【讨论】:

    • 请注意,LinuxThreads 实现已完全过时,并且自 glibc 2.3 起就不再受支持(尽管 NPTL 实现大致相同 - pthread_mutex_destroy() 只是检查一个健壮的互斥锁是否已解锁,并且将互斥锁设置为无效值)。
    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多