IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Segmentation mémoire 2, le retour


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Par défaut Segmentation mémoire 2, le retour
    Bonsoir à tous,

    Après un premier épisode palpitant, revoici Vrashnak et ses programmes qui passent la compilation mais qui foirent magistralement à l'exécution.
    Je m'explique : ce programme est censé simuler une caisse de supermarché et utilise des threads pour calculer une moyenne arithmétique, une moyenne quadratique et une somme des cubes des éléments d'un tableau d'entiers.
    A l'éxécution, une erreur de segmentation mémoire apparaît après que les "clients" aient finis leurs "achats" (les tableaux sont remplis, et on va lancer les threads).

    Ci-dessous le code du programme (très long, je m'en excuse)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <math.h>
    #include <pthread.h>
    #define MAXP 50
    #define MAXC 5000
    #define PRIXMAX 99
    struct Cli
    {
    int id;
    int *chariot;
    };
     
    typedef struct Cli Client;
    /*Ls trois fonctions suivantes permettent de simuler le comportement de la caissière
    Les fonctions sont adaptées à l'utilisation par un thread de type pthread_t*/
    void* Moyenne (void* pdata)
    {
    	double* somme=malloc(sizeof(double));
    	*somme=0;
    	int* moyenne=(int*)pdata;
    	for (int i=0; i<MAXP; i++)
    	{
    		*somme+=(double)*(moyenne+i);
    	}
    	*somme/=MAXP;
    	return (void*) somme;
    }
     
    void* Quadratique(void* pdata)
    {
    	double* somme=malloc(sizeof(double));
    	*somme=0;
    	int* moyenne=(int*)pdata;
    	for (int i=0; i<MAXP; i++)
    	{
    		*somme+=(double)((*(moyenne+i))*(*(moyenne+i)));
    	}
    	*somme/=MAXP;
    	*somme=sqrt(*somme);
    	return (void*) somme;
    }
     
    void* Cube(void* pdata)
    {
    	double* somme=malloc(sizeof(double));
    	*somme=0;
    	int* moyenne=(int*)pdata;
    	for (int i=0; i<MAXP; i++)
    	{
    		*somme+=(double)((*(moyenne+i))*(*(moyenne+i))*(*(moyenne+i)));
    	}
    	return (void*) somme;
    }
    int main()
    {
    	int prix, i;
    	Client *p=malloc(MAXC*sizeof(struct Cli));
    	srand(time(NULL));
    	pthread_t moy, qua, cub;
    	//void* 
    	void** un;
    	void** deux;
    	void** trois;
    	double* val;
    	double histo[MAXC][3];
    	printf("Ouverture du magasin.\n");
    	//Initialisation des clients
    	for(i=0;i<MAXC;i++)
    	{
    		Client *Cl=p+i;
    		Cl->id=i;
    		Cl->chariot=malloc(MAXP*sizeof(int));
    	}
    	printf("Les clients entrent dans le magasin.\n");
    	//Les clients rentrent tous dans le magasin (pas de valeur max de clients en même temps)
    	for(i=0;i<MAXC;i++)
    	{
    		for(int j=0;j<MAXP;j++)
    		{
    			p[i].chariot[j]=(rand()%PRIXMAX)+1;
    		}
    	}
    	printf("Les clients passent à la caisse.\n");
    	//Calcul multithreadé du ticket de chaque client
    	for(i=0;i<MAXC;i++)
    	{
    		Client tmp;
    		tmp=*(p+i);
    		(void*)tmp.chariot;
    		//on lance les trois threads de façon quasi-simultanée
    		pthread_create(&moy,NULL,Moyenne,tmp.chariot);
    		pthread_create(&qua,NULL,Quadratique,tmp.chariot);
    		pthread_create(&cub,NULL,Cube,tmp.chariot);
    		//récupération de la valeur renvoyée par le premier thread
    		pthread_join(moy,un);
    		val=(double*)*un;
    		histo[i][0]=(double)*val;
    		//récupération du second thread
    		pthread_join(qua,deux);
    		val=(double*)*deux;
    		histo[i][1]=(double)*val;
    		//récupération du troisième thread
    		pthread_join(cub,trois);
    		val=(double*)*trois;
    		histo[i][2]=(double)*val;
    		free(un);
    		free(deux);
    		free(trois);
    		free(val);
    	}
    	printf("Les clients sortent du magasin.\n");
    	//Libération de la mémoire allouée à chaque client
    	for(i=0;i<MAXC;i++) 
    	{
        	free(p[i].chariot);
    	}
    	free(p);
    	printf("Fermeture du magasin.\n");
    	//Affichage de tous les tickets des clients
    	for(i=0;i<MAXC;i++)
    	{
    		printf("Ticket du client %d : %0.4f %0.4f %0.4f \n",i,histo[i][0],histo[i][1],histo[i][2]);
    	}
    }
    Et le résultat à l'exécution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [vrashnak@Reghar Theorie_Systeme_Exploitation]$ time ./thr
    Ouverture du magasin.
    Les clients entrent dans le magasin.
    Les clients passent à la caisse.
    Erreur de segmentation (core dumped)
     
    real	0m0.335s
    user	0m0.013s
    sys	0m0.041s
    D'après ce que je vois, le problème vient clairement de la partie de code constituée par la boucle utilisant les threads. J'en ai donc déduit que mes pointeurs de threads étaient à refaire, mais j'ai beau chercher, je ne vois pas comment corriger le bousin, chaque correction me créant une erreur de compilation.

    Avez-vous une idée ?

    Cordialement,

    Vrashnak

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Je ne comprend pas pourquoi tu fait un free(val).
    Tu fais trois malloc dans tes threads que tu libères avec free(un); free(deux); free(trois);.
    Que libère donc val?

    Bon après, c'est le soir donc je n'ai plus toute mes capacités

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Par défaut
    J'ai fait un free(val) car je pense devoir libérer la mémoire utilisée pour stocker le résultat de mes threads. En effet, val est un pointeur, et il reçoit des valeurs. J'ai donc mis un free(val) en me disant que ça éviterait certains problèmes.
    Si ce n'est pas nécessaire, tant mieux, ça me fera une ligne de moins

    Ai-je bien expliqué ?

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonjour,

    bon, j'ai rapidement recompilé, passé au debuggueur et par valgrind pour trouver que :

    tu déclares un comme un void**
    tu l'utilises directement avec un pthread_join
    un contient n'importe quoi (très probablement pas 0 = NULL), donc pthread_join croit que c'est l'adresse VALIDE (alors qu'elle ne l'est pas) d'un pointeur sur void (void*) et essaye d'y écrire : boum ! seg fault.
    déclare ton un comme un pointeur sur void :
    ensuite passe son adresse à pthread_join :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pthread_join(moy, &un);
    val=(double*)un;
    Évidemment il y a le même problème avec deux et trois ...
    Je n'ai pas checké plus avant le programme ...

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Par défaut
    Tout d'abord, merci kwariz pour ton aide. Ca fait vraiment plaisir.

    J'ai appliqué tes modifications sur le code. Pas de problème à la compilation, mais à l'exécution, BOUM !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    [vrashnak@Reghar Theorie_Systeme_Exploitation]$ time ./thr
    Ouverture du magasin.
    Les clients entrent dans le magasin.
    Les clients passent à la caisse.
    *** glibc detected *** ./thr: double free or corruption (fasttop): 0xb5e00468 ***
    ======= Backtrace: =========
    /lib/libc.so.6[0x41e05f12]
    ./thr[0x8048abb]
    /lib/libc.so.6(__libc_start_main+0xf3)[0x41da86b3]
    ./thr[0x8048581]
    ======= Memory map: ========
    08048000-08049000 r-xp 00000000 fd:02 12586330   /home/vrashnak/Documents/Licence/L3/Theorie_Systeme_Exploitation/thr
    08049000-0804a000 rw-p 00001000 fd:02 12586330   /home/vrashnak/Documents/Licence/L3/Theorie_Systeme_Exploitation/thr
    08fbf000-090d0000 rw-p 00000000 00:00 0          [heap]
    41d6a000-41d8b000 r-xp 00000000 fd:01 32389      /lib/ld-2.14.90.so
    41d8b000-41d8c000 r--p 00020000 fd:01 32389      /lib/ld-2.14.90.so
    41d8c000-41d8d000 rw-p 00021000 fd:01 32389      /lib/ld-2.14.90.so
    41d8f000-41f36000 r-xp 00000000 fd:01 32390      /lib/libc-2.14.90.so
    41f36000-41f37000 ---p 001a7000 fd:01 32390      /lib/libc-2.14.90.so
    41f37000-41f39000 r--p 001a7000 fd:01 32390      /lib/libc-2.14.90.so
    41f39000-41f3a000 rw-p 001a9000 fd:01 32390      /lib/libc-2.14.90.so
    41f3a000-41f3d000 rw-p 00000000 00:00 0 
    41f3f000-41f56000 r-xp 00000000 fd:01 32391      /lib/libpthread-2.14.90.so
    41f56000-41f57000 r--p 00016000 fd:01 32391      /lib/libpthread-2.14.90.so
    41f57000-41f58000 rw-p 00017000 fd:01 32391      /lib/libpthread-2.14.90.so
    41f58000-41f5a000 rw-p 00000000 00:00 0 
    41f6f000-41f98000 r-xp 00000000 fd:01 1228       /lib/libm-2.14.90.so
    41f98000-41f99000 r--p 00028000 fd:01 1228       /lib/libm-2.14.90.so
    41f99000-41f9a000 rw-p 00029000 fd:01 1228       /lib/libm-2.14.90.so
    41fb4000-41fd0000 r-xp 00000000 fd:01 32408      /lib/libgcc_s-4.6.3-20120306.so.1
    41fd0000-41fd1000 rw-p 0001b000 fd:01 32408      /lib/libgcc_s-4.6.3-20120306.so.1
    b5a00000-b5a21000 rw-p 00000000 00:00 0 
    b5a21000-b5b00000 ---p 00000000 00:00 0 
    b5c00000-b5c21000 rw-p 00000000 00:00 0 
    b5c21000-b5d00000 ---p 00000000 00:00 0 
    b5e00000-b5e21000 rw-p 00000000 00:00 0 
    b5e21000-b5f00000 ---p 00000000 00:00 0 
    b5fcd000-b5fce000 ---p 00000000 00:00 0 
    b5fce000-b67ce000 rw-p 00000000 00:00 0 
    b67ce000-b67cf000 ---p 00000000 00:00 0 
    b67cf000-b6fcf000 rw-p 00000000 00:00 0 
    b6fcf000-b6fd0000 ---p 00000000 00:00 0 
    b6fd0000-b77d2000 rw-p 00000000 00:00 0 
    b77ec000-b77ef000 rw-p 00000000 00:00 0 
    b77ef000-b77f0000 r-xp 00000000 00:00 0          [vdso]
    bfbe5000-bfc06000 rw-p 00000000 00:00 0          [stack]
    Abandon (core dumped)
     
    real	0m0.315s
    user	0m0.017s
    sys	0m0.087s
    Et là, j'admets que je panique légèrement... En fait, j'admets ne même pas comprendre le message d'erreur.
    EDIT : alors (corrigez moi si je me trompe), je crois comprendre que la deuxième partie représente l'utilisation mémoire et le stockage des valeurs renvoyées par les threads avec les adresses correspondantes. Mais comment l'interpréter ?
    Et même en tapant ce qui me semble être les mots-clés sur Google, rien de bien probant...

    En revanche, je viens de percuter : j'aurais du préciser que je travaille sous Fedora 16...

    Que puis-je faire pour éviter ces codes d'erreurs ?

  6. #6
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bon, il y a plusieurs outils qui sont indispensables quand tu as des erreurs : le débuggueur (pour savoir où et essayer de comprendre pourquoi ça plante) et Valgrind (qui montre où tu as des problèmes potentiels avec ta gestion de la mémoire).

    Neckara t'a donné la solution à cette erreur (double free or corruption)

    Tu ne dois faire de free que si tu as fais un malloc avant.
    Tu as fais des malloc dans les fonctions threads, tu récupères les "variables" mallocées dans un deux et trois que tu free (normal). En revanche tu n'utilises val que pour pointer aux mêmes endroits que un deux et trois sans jamais allouer de mémoire : il ne faut pas faire de free de val.

    Avant les free, val et trois pointent sur la même zone mémoire, tu la free avec un free(trois) et tu réessayes de la libérer avec free(val) : double free.

    Mais Neckara l'a mieux expliqué que moi

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Aide] problème de segmentation mémoire
    Par Vrashnak dans le forum Débuter
    Réponses: 6
    Dernier message: 06/10/2012, 19h24
  2. Question sur la segmentation mémoire
    Par Flynet dans le forum Assembleur
    Réponses: 4
    Dernier message: 30/05/2011, 17h58
  3. Erreur de segmentation : mémoire tampon?
    Par sayanmehdi dans le forum C
    Réponses: 5
    Dernier message: 02/06/2010, 16h23
  4. [IPC] libération segment mémoire partagée
    Par joyled dans le forum Linux
    Réponses: 10
    Dernier message: 31/12/2008, 00h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo