pthread: уничтожение глобального статического мьютекса

Этот код был взят из 3-го издания расширенного программирования в среде UNIX, написанного Ричардом Стивенсом. Это пример того, как создать повторную версию getenv() . Здесь он демонстрируется только для целей обучения.

 /* Copyright (c) WRStevens */ #include  #include  #include  #include  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() . Однако мьютекс будет нерекурсивным.

Можно написать простой class C ++, который может уничтожить мьютекс в деструкторе. Тем не менее, он не подходит для всех, у кого есть только компилятор C (и, похоже, это фигня, чтобы использовать компилятор C ++ из-за одной функции).

Другая вещь, которая приходит на ум, – это расширения для компилятора, такие как __attribute__((destructor)) в GCC (и, надеюсь, clang). Однако он не переносится.

Можно ли избежать утечки памяти? Если да, как это можно сделать в C?

ОБНОВЛЕНИЕ Как показано в «Программирование с streamами POSIX», написанном Дэвидом Бутенхофом, нам никогда не нужно уничтожать вариант PTHREAD_MUTEX_INITIALIZER . Как насчет мьютексов с другими атрибутами?

Ресурсы, которые все еще живут при завершении процесса, не являются утечками памяти, несмотря на некоторые наивные инструменты, classифицирующие их как таковые. Утечка памяти – это необратимый и неограниченный рост требований к ресурсам программы в течение ее жизненного цикла, что непропорционально фактическому рабочему набору.

В POSIX (где вы получаете streamи POSIX), все локальные ресурсы процесса перестают существовать при завершении программы. Не нужно явно их уничтожать / освобождать, а в некоторых случаях, как и вы, вы не можете безопасно уничтожить / освободить их, и вы не должны пытаться .

Отсутствие утечки памяти из-за того, что переменные pthread_mutex_t живут в пользовательской памяти, при выходе процесса все выделенные пользователем память восстанавливаются. Утечки памяти возникают, когда что-то выделяет кучную память, например, strdup. И тогда вы его не очищаете.

Если бы это было

 pthread_mutex_t *foo; .... foo =malloc(sizeof(pthread_mutex_t); 

А потом не освобождается бесплатно, что создает утечку памяти – если тогда foo получил выделение на новую память. Однако при завершении процесса ALL памяти запрошенный процесс, включая кучу, восстанавливается ОС. Стивенс объясняет это в главе о процессах. Этот код не течет.