pthread_exit vs retour
J'ai un recrutables pthread coureur de la fonction définie comme ci-dessous:
void *sumOfProducts(void *param)
{
...
pthread_exit(0);
}
Ce fil est censé rejoindre le thread principal.
Chaque fois que j'ai couru mon programme par le biais de Valgrind, je voudrais obtenir le suite à des fuites:
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 968 bytes in 5 blocks
suppressed: 0 bytes in 0 blocks
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 10)
J'ai vérifié la page de man pour les pthreads qui a dit:
The new thread terminates in one of the following ways:
* It calls pthread_exit(3), specifying an exit status value that is
available to another thread in the same process that calls
pthread_join(3).
* It returns from start_routine(). This is equivalent to calling
pthread_exit(3) with the value supplied in the return statement.
* It is canceled (see pthread_cancel(3)).
* Any of the threads in the process calls exit(3), or the main thread
performs a return from main(). This causes the termination of all
threads in the process.
Miraculeusement, quand j'ai remplacé le pthread_exit() avec une instruction de retour, les fuites disparu.
return(NULL);
Ma réelle question est de trois volets:
- Quelqu'un peut m'expliquer pourquoi l'instruction return a donné aucune fuite?
- Est-il une différence fondamentale entre les deux états, en ce qui concerne la sortie de threads?
- Si oui, où doit-on la préférence sur les autres?
- Êtes-vous vraiment à l'aide de C++? C++ utilise portée pour détruire les objets et le retour de "laisser" que la portée de tout pthread_exit ne sera pas.
- Je suis désolé, mais je n'ai jamais mentionner le C++ n'importe où dans ma question. Je suis de tout faire en C à partir de maintenant.
- Je sais que tu ne l'ai pas mentionné, mais c'était une supposition, c'est pourquoi j'ai demandé. 🙂 Pourriez-vous fournir un ensemble de test cas?
Vous devez vous connecter pour publier un commentaire.
Minimales suivantes de cas de test présente le comportement que vous décrivez:
valgrind --leak-check=full --show-reachable=yes
montre 5 blocs attribués pour les fonctions appelées parpthread_exit()
qui est unfreed mais toujours accessible à la sortie du processus. Si lepthread_exit(0);
est remplacé parreturn 0;
, le 5 blocs ne sont pas affectés.Toutefois, si vous testez la création et de rejoindre un grand nombre de threads, vous trouverez que le montant de unfreed de la mémoire en cours d'utilisation à la sortie ne pas augmentation. Cela, et le fait qu'il est toujours accessible, indique que vous voyez juste une bizarrerie de la mise en œuvre de la glibc. Plusieurs glibc fonctions d'allouer de la mémoire avec
malloc()
la première fois qu'ils sont appelés, qu'ils gardent alloué pour le reste de la vie du processus. la glibc ne prend pas la peine de libérer cette mémoire à la sortie du processus, puisqu'il sait que le processus est en train d'être déchirée vers le bas de toute façon - il avait juste être un gaspillage de cycles CPU.__libc_freeres
qui est censé le faire. Cependant, il y a quelques versions de la glibc qui ont des bugs dans cette fonction (comme il est généralement appelé pas moins que le programme est en cours d'exécution en vertu d'un débogueur mémoire). Il est généralement appelé par défaut, à moins que valgrind est exécuté avec l'argument--run-libc-freeres=no
.Ne sais pas si vous êtes toujours intéressé, mais je suis actuellement en train de débogage d'une situation similaire. Les Threads qui utilisent
pthread_exit
cause valgrind de rapport accessible blocs. La raison semble être assez bien expliqué ici:https://bugzilla.redhat.com/show_bug.cgi?id=483821
Essentiellement, il semble
pthread_exit
provoque unedlopen
qui n'est jamais nettoyé explicitement lorsque le processus s'arrête.Il ressemble à l'appel de exit() (et, apparemment, pthread_exit()) quitte automatiquement affectés variables allouées. Vous devez retourner ou de le jeter dans le but de bien se détendre.
Par C++ valgrind fuites possibles sur STL chaîne:
Depuis de faire un "return 0" au lieu de "pthread_exit(0)" a semblé résoudre votre problème (et le mien.. merci), je suis en supposant que le comportement est similaire entre les deux.
Vous êtes réellement en utilisant le C++, par hasard? Pour préciser votre source de fichier se termine avec un
.c
extension, et vous êtes le compiler avecgcc
, pasg++
?Il semble raisonnable de penser que votre fonction est d'allouer des ressources que vous pouvez vous attendre à être nettoyé automatiquement lorsque la fonction retourne. Local des objets en C++ comme
std::vector
oustd::string
ce faire, et leurs destructeurs ne sera probablement pas fonctionner si vous appelezpthread_exit
, mais serait nettoyé si vous venez de retour.Ma préférence est pour éviter de bas niveau des Api comme
pthread_exit
, et toujours juste retour de la fonction de thread, si possible. Elles sont équivalentes, sauf quepthread_exit
est de facto le contrôle du flux de construire qui contourne la langue que vous utilisez, maisreturn
ne le fait pas.gcc
, et il n'y a pas de possibilité qu'il ou n'importe quel code il appelle pourraient être accidentellement à l'aide des fonctionnalités C++?J'ai l'expérience que valgrind a des difficultés à suivre le stockage est alloué pour l'état de recrutables threads. (Ceci va dans le même sens que la caf indique.)
Puisqu'il semble que vous avez toujours retourner une valeur de
0
je suppose que vous avez peut-être besoin de se joindre à votre threads d'une application de point de vue? Si donc envisager de les lancer détaché dès le début, cela évite l'allocation de la mémoire.L'inconvénient, c'est que soit vous avez:
à la fin de votre
main
. Si vous connaissez lenombre de threads à l'avance, une
simple allouée statiquement
pthread_barrier
ferait.main
avecpthread_exit
de telle sorte que vous n'avez pastuer le reste des threads en cours d'exécution
qui pourrait ne pas être encore fini.