bonjour,
voila je vous poste mon code ca sera plus simple pour la suite d'expliquer mon probleme.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void* f(void * arg)
{
int value = *((int*)arg);
fprintf(stdout, "thread : &value = %p ; value = %i\n", arg, value);
}
int main(int argc, char const *argv[])
{
pthread_t t;
int value = 6;
pthread_create( &t, NULL, f, (void*)&value);
printf("&value = %p ; value = %i\n", &value , value);
pthread_join( t, NULL );
return 0;
}
D'apres ce que j'ai compris des threads, c'est qu'ils font partie du meme processus mais ils possedent chacun leurs propres piles (stack). Donc les Threads peuvent lire des variables dans le tas ou dans la zones ou sont stockés les variables globales, mais il n'est pas possible de lire une variable dans la pile d'un autre thread sans déclencher un segfault.
Or dans mon code je vais lire a partir d'un thread secondaire, une variable qui se trouve sur la pile du thread principale et ca ne déclenche aucun segfault. J'en déduis donc qu'il y a quelque chose que je n'ai pas compris.
Pouvez vous m'éclairer sur ce probleme ?
Merci d'avance
# pas de protection mémoire
Posté par flavien75 . Évalué à 3.
Bonjour,
Tout d'abord, il n'y a aucun cloisonement de la mémoire entre les différents threads d'un processus. Le thread secondaire peut donc tout à fait accéder à une variable stockée dans la pile du premier, à condition bien sûr de connaître son adresse.
Par contre, les piles sont bien indépendantes ce qui est nécessaire pour que les différents threads puissent (facilement) appeler des fonctions, créer des variables locales…
Après on évite
généralementsystématiquement de partager des variables stockées dans la pile d'un autre thread car il devient rapidement compliqué de garantir que celles-ci existeront toujours au moment de l'accès.Un moyen plus sûr serait que le thread "principal" créé la variable dans le tas (malloc()), l'initialise, fasse ce qu'il a faire avec et seulement ensuite transmette l'adresse de celle-ci au thread secondaire qui se chargera de libérer la variable (free()).
Les vrais naviguent en -42
[^] # Re: pas de protection mémoire
Posté par totof2000 . Évalué à 3.
Bof … Moi je demanderais au thread secondaire de prévenir le thread principal qu'il n'a plus besoin de la ressource pour qu'il la libère. En effet, qu'est-ce qui dit qu'un autre thread secondaire n'aurait pas besoin de cette ressource ? Apres c'est une question de choix.
[^] # Re: pas de protection mémoire
Posté par flavien75 . Évalué à 1.
Ouh là… on va partir dans une discussion qui dépasse de loin la question initiale, mais pourquoi pas.
Le moyen que j'ai indiqué ne correspond bien évidement pas à tous les cas qui peuvent arriver, d'ailleurs la libération d'une variable dépend toujours du contenu et du rôle de celle-ci.
Souvent dans mes logiciels, la variable passée lors de la création du thread correspond à un "ordre de mission" pour le thread (quelle donnée traitée, quel traitement, où stocker le résultat…). Dans ce cas je voir ça comme un "don" et le destinataire est chargé de détruire proprement la variable lorsqu'il n'en a plus besoin.
Cette approche a l'avantage de supprimer les risques d'accès concurrents (par exemple la modifications d'une structure alors qu'elle est en cours de lecture par un autre thread).
Un autre cas est la variable partagée, mais dans ce cas il va souvent falloir ajouter les mutex pour gérer les accès concurrents ce qui n'est pas ce qui va assurer les meilleurs performances. Dans ce cas, le thread créant la variable pourrait être vu comme le propriétaire de la variable et aura donc à gérer sa destruction au moment opportun (soit la méthode que tu as proposée).
Les vrais naviguent en -42
[^] # Re: pas de protection mémoire
Posté par David Marec . Évalué à 4.
C'est pourquoi je cherche autant que possible à utiliser des pipes entre les threads. C'est une solution plus légère pour gérer la concurrence.
[^] # Re: pas de protection mémoire
Posté par Anthony Jaguenaud . Évalué à 3.
Je préfère passer par la pile pour passer les paramètres à un thread en utilisant les conditions.
Du coup sur le thread principal c’est préparation de la condition, démarrage du thread attente que le thread valide la condition.
Côté thread, lecture des paramètres qui se trouve dans la pile du thread principal, validation de la condition pour permettre au créateur de continuer son travail.
[^] # Re: pas de protection mémoire
Posté par nico4nicolas . Évalué à 2.
Cela ressemble beaucoup à un cas pratique d'utilisation d'un sémaphore.
# Pour ce que j'en sais...
Posté par guitou . Évalué à -2.
Au risque de dire une sottise, je crois que cela fonctionne comme pour le fork, les variables déclarées avant le fork()/pthread_create() sont connues de tous.
++
Gi)
[^] # Re: Pour ce que j'en sais...
Posté par Matthieu Moy (site web personnel) . Évalué à 5.
Avec une très grosse différence : avec
fork
, la mémoire est en copy-on-write, donc les accès en écriture d'un processus ne sont pas visibles depuis un autre processus. Avecpthread_create
, la mémoire est vraiment partagée, en lecture et en écriture.# espace utilisateur
Posté par David Marec . Évalué à 4. Dernière modification le 13 octobre 2019 à 15:39.
Oui, ils vivent dans le même espace mémoire virtuel.
Oui, allouées dans cet espace.
De fait, ils peuvent lire des variables allouées dans l'espace mémoire dédié au processus.
Ah ? D'où tenez vous cette assertion ?
Votre programme, qui est tout à fait valide, est la preuve du contraire.
Le risque avec les threads est de mal maîtriser les flux d’exécution et de demander à accéder à une variable qui a été libérée, que soit parce qu'elle était dans le scope d'un thread qui s'est terminé ou parce qu'elle a été libérée explicitement.
Et même là, le risque de segfault est faible, vous allez probablement taper dans un espace toujours réservé pour votre processus. Par contre, pour ce qui est de la valeur que vous allez récupérer, ça dépendra du sens du vent.
# c'est compris
Posté par cosmoff . Évalué à 1.
c'est beaucoup plus claire merci d'avance pour vos éclaircissements
# Clarification de undefined behavior
Posté par David Demelier (site web personnel) . Évalué à 1.
Plop,
Beaucoup de gens pensent à tort que “Undefined Behavior” va générer un crash. Ce n'est pas requis. Par exemple, rien n'empêche à une implémentation d'autoriser l'écriture sur un pointeur nul, la norme dit simplement que c'est un comportement indéfini.
Ici il n'y a aucune raison que ça crash d'autant que le code est valide puisque tu ne modifie pas la variable dans ton thread que tu as passé en argument. Et encore heureux qu'on puisse lire les objets passés en arguments dans un thread sinon bonjour leur utilité ! ;-)
git is great because linus did it, mercurial is better because he didn't
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.