C++ 有必要在互斥体上调用pthread_mutex_destroy吗?

C++ 有必要在互斥体上调用pthread_mutex_destroy吗?,c++,pthreads,posix,mutex,C++,Pthreads,Posix,Mutex,我在C++程序中使用pthRead MutExtt,如下: class Mutex : public noncopyable { public: Mutex() { pthread_mutex_init(&m_mutex, NULL); } void acquire() { pthread_mutex_lock(&m_mutex); } void release() {

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

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;
};
(该类不可复制-)

我不明白的是,在析构函数中不调用
pthread\u mutex\u destroy
是否被视为错误?我读过的文档没有说明必须调用destroy

有人知道吗,
pthread\u mutex\u destroy实际上是做什么的,在什么条件下需要它

编辑

pthread\u mutex\u destroy
的答案是否也适用于
pthread\u cond\u destroy
等?它们对我来说几乎是无用的函数,除非
pthread\u mutex\u init
等正在分配内存?(在我看来,文件对此并不完全清楚。)

无论如何,我打电话给destroy并没有什么坏处,所以这个问题主要是学术性的。

无论如何,在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)。

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

在API不起作用的体系结构和实现上,这将被优化掉,但是如果API将来更改为需要清除内部状态,并且您的代码没有调用它,那么您的代码现在将出现内存和/或资源泄漏

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

来自,这是管理POSIX的标准:

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

文档并没有说您必须调用它。但这样做是一种很好的做法。
调用此api将向POSIX库发送信号,以释放为在初始化期间使用此特定互斥对象而保留的所有资源。

假设互斥初始化确实分配/保留了一些资源是合乎逻辑的。

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

以下是最新消息的摘录:


事实上,有趣的是,文档中并没有说你需要销毁。似乎是编写它的人的疏忽。Create/Destroy是C代码中的一种常见模式,大多数开发人员和文档编写人员都想当然地认为,如果他们为您提供了一个“Destroy”方法,那么您必须在调用init之后但在对象超出范围之前调用它。@thang:pthread_mutex是一个结构,不是C++类。它没有C++析构函数。这就是pthread_mutex_destroy存在的原因。当您调用pthread_mutex_init而不调用pthread_mutex_destroy时会发生什么的问题是实现定义的。在某些平台上,不会发生什么坏事。在其他系统上,它可能会导致长时间运行的服务器进程崩溃。这就是为什么您不为实现编程的原因。您可以使用API编程。API说,完成后调用pthread_mutex_destroy。如果你使用API编程,你的代码很可能会在野外工作。谢谢大家的热烈讨论。答案当然是肯定的,因为在避免潜在问题的同时,调用destroy的成本非常低。我想这个问题更多的是出于我对实际发生的事情的好奇(我怀疑销毁实际上什么都没有),但现在我甚至问这个问题都觉得很傻——我只是没有从文档中得到一个直接的答案,所以我来到这里。整个讨论都很傻。销毁互斥锁的正确而可靠的方法是拔掉系统的插头。实际上,文件甚至没有说这样做是一种好的做法:p我认为这是对编写它的人的疏忽。例如,在windows中。使用CloseHandle功能关闭手柄。当进程终止时,系统自动关闭句柄。互斥对象在其最后一个句柄被关闭时被销毁。@thang:我不确定这是否是一个洞察,但对我来说,这样做似乎很合乎逻辑。如果你真的想学究式地深究它,那么编写一个小的示例程序就很容易了。在ValGRD下运行它,同时检查系统资源,并调用函数,而不需要C++函数。查看有关指定方式的所有细节。没有什么是留给想象的。。。为什么这是一个例外?@:C和C++标准是相当全面的,可能是因为大量的编译器实现需要坚持它们,而不是IEEE的情况。这只是一个猜测。我没有权力在确信的情况下提出这样的要求。此外,我不认为只有IEEE委员会的某个人才能权威地回答为什么这是一个例外的确切原因。我怀疑这只是一个小疏忽。事实上,正如我在下面提到的,在其他操作系统中(呃,至少还有一个操作系统:与可以在线程之间共享的任何系统资源一样,在线程终止之前,必须销毁线程堆栈上分配的互斥锁)实际上在他们的文档中明确说明了这一点。请注意,此windows实现需要销毁:而此windows实现不需要销毁。
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;
}