这段代码摘自Richard Stevens所著的《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
。那么其他属性的互斥锁呢?