pthread: destruction du mutex statique global

Ce code provient de la 3ème édition de Advanced Programming in UNIX Environment, écrite par Richard Stevens. Ceci est un exemple de la manière de créer une version réentrante de getenv() . Il est présenté ici uniquement à des fins d’apprentissage.

 /* 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); } 

Ce code est facile à comprendre. Cependant j’ai une question. Nous n’appelons jamais pthread_mutex_destroy() , ce qui signifie qu’il peut y avoir une fuite de mémoire à la sortie (je suppose que cela peut différer d’une plate-forme à l’autre).

La première chose qui me vient à l’esprit est que l’on peut utiliser PTHREAD_MUTEX_INITIALIZER . Est-ce que cela nécessite un appel à pthread_mutex_init() ? Si non, il n’est pas nécessaire d’appeler pthread_mutex_destroy() . Cependant, le mutex sera non-récursif.

On pourrait écrire une simple classe C ++ qui pourrait détruire mutex dans destructor. Cependant, il ne convient pas à ceux qui possèdent uniquement le compilateur C (et il semble que ce soit une connerie d’utiliser le compilateur C ++ à cause d’une fonction).

L’autre chose qui me vient à l’esprit est des extensions spécifiques au compilateur, telles que __atsortingbute__((destructor)) dans GCC (et, espérons-le, clang). Cependant, il n’est pas portable.

Est-il possible d’éviter une fuite de mémoire? Si oui, comment cela peut-il être fait en C?

UPDATE Comme cela apparaît dans “Programmer avec les threads POSIX” de David Butenhof, nous n’avons jamais besoin de détruire la variante PTHREAD_MUTEX_INITIALIZER . Qu’en est-il des mutex avec d’autres atsortingbuts?

Les ressources qui sont toujours actives à la fin du processus ne constituent pas des memory leaks, bien que certains outils naïfs les aient classées comme telles. Une fuite de mémoire est une croissance irréversible et illimitée des besoins en ressources d’un programme au cours de sa durée de vie qui est disproportionnée par rapport à l’ensemble de travail réel.

Selon POSIX (où se trouvent les threads POSIX), toutes les ressources locales au processus cessent d’exister à la fin du programme. Il n’est pas nécessaire de les détruire / les libérer explicitement, et dans certains cas, comme le vôtre, vous ne pouvez pas les détruire / libérer en toute sécurité et vous ne devez pas essayer .

Pas de fuite de mémoire car les variables pthread_mutex_t dans la mémoire utilisateur. En sortie de processus, toute la mémoire allouée par l’utilisateur est récupérée. Les memory leaks se produisent lorsque quelque chose alloue de la mémoire, comme strdup. Et puis vous ne nettoyez pas.

Si c’était alloué comme

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

Et puis non libéré avec free qui crée une fuite de mémoire – si foo est alloué à plus de mémoire. Cependant, à la fin du processus, TOUTES les mémoires demandées sont récupérées par le système d’exploitation, processus compris. Stevens l’explique dans le chapitre sur les processus. Ce code ne fuit pas.