c - pthread : destroying global static mutex

标签 c pthreads reentrancy

此代码摘自 Richard Stevens 编写的第 3 版 UNIX 环境中的高级编程。这是一个如何制作 getenv() 的可重入版本的示例。此处演示仅供学习。

/* Copyright (c) W.R.Stevens */
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>

extern char **environ;

pthread_mutex_t env_mutex;

static pthread_once_t init_done = PTHREAD_ONCE_INIT;

static void
thread_init(void)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&env_mutex, &attr);
    pthread_mutexattr_destroy(&attr);
}

int
getenv_r(const char *name, char *buf, int buflen)
{
    int i, len, olen;

    pthread_once(&init_done, thread_init);
    len = strlen(name);
    pthread_mutex_lock(&env_mutex);
    for (i = 0; environ[i] != NULL; i++) {
        if ((strncmp(name, environ[i], len) == 0) &&
          (environ[i][len] == '=')) {
            olen = strlen(&environ[i][len+1]);
            if (olen >= buflen) {
                pthread_mutex_unlock(&env_mutex);
                return(ENOSPC);
            }
            strcpy(buf, &environ[i][len+1]);
            pthread_mutex_unlock(&env_mutex);
            return(0);
        }
    }
    pthread_mutex_unlock(&env_mutex);
    return(ENOENT);
}

这段代码很容易理解。但我有个问题。我们从不调用 pthread_mutex_destroy(),这意味着退出时可能会发生内存泄漏(我猜这可能因平台而异)。

首先想到的是可以使用 PTHREAD_MUTEX_INITIALIZER。是否需要 pthread_mutex_init() 调用?如果不是,则无需调用 pthread_mutex_destroy()。但是,互斥量将是非递归的。

可以编写一个简单的 C++ 类,在析构函数中销毁互斥量。但是,它并不适合任何只有C编译器的人(而且因为一个功能而使用C++编译器似乎是在扯淡)。

想到的另一件事是特定于编译器的扩展,例如 GCC 中的 __attribute__((destructor))(希望是 clang)。但是,它是不可携带的。

是否有可能避免内存泄漏?如果是,如何在 C 中完成?

更新 正如 David Butenhof 所写的“Programming with POSIX threads”中所述,我们永远不需要销毁 PTHREAD_MUTEX_INITIALIZER 变体。具有其他属性的互斥锁怎么样?

最佳答案

在进程终止时仍然存在的资源不是内存泄漏,尽管一些简单的工具将它们归类为内存泄漏。内存泄漏是程序在其生命周期内对资源需求的不可逆转和无限增长,这与实际工作集不成比例。

根据 POSIX(这是您获得 POSIX 线程的地方),所有进程本地资源在程序终止时不再存在。没有必要明确地销毁/释放它们,在某些情况下,例如您的情况,您不能安全地销毁/释放它们并且您不应该尝试

关于c - pthread : destroying global static mutex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26899569/

相关文章:

c - 在结构指针中引用结构指针

c - 堆栈在 32 位和 64 位处理器中有何不同

c++ - Linux 上的 pthread_self

线程之间可以安全地共享整数吗?

c++ - 只有当我们有多个线程时才会出现不可重入问题吗?

.net - 检测到重入

c - 从文件中读取数组大小

c++ - 检查变量是否已被垃圾收集器声明

php - 在 Ubuntu 上的 PHP+Apache2 中启用线程安全 - 使用 pthreads 从源代码编译 php

c - 使用 `_r` 时是否需要显式使用 `-D_REENTRANT` 后缀?