16

我在 C++ 程序中使用 pthread_mutex_t,如下:

class Mutex : public noncopyable
{
public:
    Mutex()
    {
        pthread_mutex_init(&m_mutex, NULL);
    }

    void acquire()
    {
        pthread_mutex_lock(&m_mutex);
    }

    void release()
    {
        pthread_mutex_unlock(&m_mutex);
    }

private:
    pthread_mutex_t m_mutex;
};

(该课程不可复制 - http://www.boost.org/doc/libs/1_53_0/boost/noncopyable.hpp

我不明白的事情 -调用pthread_mutex_destroy析构函数是否被视为错误?我读过的文档没有说明必须调用destroy。

有谁知道,pthread_mutex_destroy实际做什么以及在什么条件下需要它?

编辑

的答案是否pthread_mutex_destroy也适用于pthread_cond_destroy等?对我来说,它们似乎几乎是无用的功能,除非pthread_mutex_init等。人。正在分配内存?(对我来说,文档对此并不完全清楚。)

无论如何,调用破坏并没有伤害我,所以这个问题主要是学术性的。

无论如何,在 linux 上,似乎 destroy 只会将互斥锁设置为无效状态:

int
__pthread_mutex_destroy (mutex)
     pthread_mutex_t *mutex;
{
  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
      && mutex->__data.__nusers != 0)
    return EBUSY;

  /* Set to an invalid value.  */
  mutex->__data.__kind = -1;

  return 0;
}

(来自 glibc-2.14/nptl/pthread_mutex_destroy.c)。

4

3 回答 3

18

如果有人为您提供了一个销毁函数,那么您需要在该对象超出范围之前调用它作为对该对象的最终操作。

在 API 没有影响的架构和实现上,这将被优化掉,但是如果 API 将来更改为需要清理内部状态并且您的代码没有调用它,您的代码现在将拥有内存和/或资源泄漏。

所以简单的答案是肯定的;你必须调用这个 API——事情就是这样——即使 API 目前什么都不做,因为虽然 API 本身在未来永远是固定的,但 API 背后的实现却不是。

于 2013-02-06T04:00:27.113 回答
8

来自IEEE 文档,它是管理 POSIX 的标准:

pthread_mutex_destroy() 函数将销毁 mutex 引用的 mutex 对象;互斥对象实际上变得未初始化。实现可能会导致 pthread_mutex_destroy() 将 mutex 引用的对象设置为无效值。可以使用 pthread_mutex_init() 重新初始化被破坏的互斥对象;在对象被销毁后以其他方式引用该对象的结果是未定义的。

文档没有说你必须调用它。但这样做是一个好习惯。
调用此 api 将向 POSIX 库发出信号,以释放在其初始化期间为该特定互斥对象使用而保留的所有资源。
假设互斥锁初始化确实分配/保留了一些资源是合乎逻辑的。

于 2013-02-06T04:02:21.547 回答
4

几年过去了,@SecurityMatt 是对的。为了解决争论,您必须调用 pthread_mutex_destroy 以满足 API 要求并释放内存。

这是最新的pthread_mutex_destroy的摘录:

int _pthread_mutex_destroy (pthread_mutex_t *mutex)
{
  if (mutex->__attr == __PTHREAD_ERRORCHECK_MUTEXATTR
      || mutex->__attr == __PTHREAD_RECURSIVE_MUTEXATTR)
    /* Static attributes.  */
    ;
  else
    free (mutex->__attr);

  return 0;
}
于 2019-01-22T03:25:42.010 回答