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

Linux Discussion :

Valgrind erreur incomprise


Sujet :

Linux

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 123
    Points : 85
    Points
    85
    Par défaut Valgrind erreur incomprise
    Bonjour

    J'ai programmé une pile FILO d'entiers en C.
    Et je me suis dit que j'allais tester le code avec valgrind qui me sort deux erreurs que je ne comprends pas . Je suis novice avec cet outil alors je ne sais pas si se sont des faux positifs ou si je dois en tenir compte.

    Voila le code:

    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
     
     
    #include <stdio.h>
    #include <stdlib.h>
    /*
    *	Element de la pile.
    */
    struct Element
    {
    	int value;				// Le contenu de la liste chainée
    	struct Element *next;	// L'élément suivant de la liste chainée.
    };
     
    typedef struct Element* Stack;
     
    Stack initialize(int value);
    void push(Stack* stack, int value);
     
    int main(void)
    {	
    	Stack stack = NULL;
    	push(&stack, 0);
    	free(stack);
    	return 0;
    }
     
    /*
    *	Crée, alloue dynamiquement et initialise un élément.
    *	@param value	La valeur de l'élément.
    *	@return 		Si l'allocation réussit, retourne l'élément initialisé
    *					dynamiquement, sinon retourne la valeur NULL.
    */
    Stack initialize(int value)
    {
    	Stack stack = NULL;
    	stack = malloc(sizeof(stack));
     
    	if(stack != NULL)
    	{
    		stack->value = value;
    	}
    	else
    	{
    		perror("Impossible d'allouer dynamiquement un élément");
    	}
    	return stack;
    }
     
    /*
    *	Ajoute un élément dans la pile.
    *	@param stack	Un pointeur de pointeur sur la pile dans laquelle l'élément sera ajouté.
    *	@param value	La valeur à ajouter dans la pile.
    */
    void push(Stack* stack, int value)
    {
    	Stack element = initialize(value);
    	element->next = (*stack);
    	(*stack) = element;
    }
    Voila la ligne de commande avec laquelle je compile:
    valgrind --tool=memcheck --leak-check=full --leak-resolution=high --show-reachable=yes ./integerStack

    Et voila les erreurs:

    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
     
    ==9766== Invalid write of size 4
    ==9766==    at 0x80484EC: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==  Address 0x418502c is 0 bytes after a block of size 4 alloc'd
    ==9766==    at 0x4022AB8: malloc (vg_replace_malloc.c:207)
    ==9766==    by 0x80484AB: initialize (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x80484E0: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766== 
    ==9766== Invalid read of size 4
    ==9766==    at 0x80485C7: printStack (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x8048479: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==  Address 0x418502c is 0 bytes after a block of size 4 alloc'd
    ==9766==    at 0x4022AB8: malloc (vg_replace_malloc.c:207)
    ==9766==    by 0x80484AB: initialize (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x80484E0: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    Quelqu'un pourrait-il m'expliquer le problème


    ET l'erreur

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 739
    Points : 31 068
    Points
    31 068
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Anonymouse Voir le message
    Bonjour

    J'ai programmé une pile FILO d'entiers en C.
    Et je me suis dit que j'allais tester le code avec valgrind qui me sort deux erreurs que je ne comprends pas . Je suis novice avec cet outil alors je ne sais pas si se sont des faux positifs ou si je dois en tenir compte.

    Voila le code:

    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
     
     
    #include <stdio.h>
    #include <stdlib.h>
    /*
    *	Element de la pile.
    */
    struct Element
    {
    	int value;				// Le contenu de la liste chainée
    	struct Element *next;	// L'élément suivant de la liste chainée.
    };
     
    typedef struct Element* Stack;
     
    Stack initialize(int value);
    void push(Stack* stack, int value);
     
    int main(void)
    {	
    	Stack stack = NULL;
    	push(&stack, 0);
    	free(stack);
    	return 0;
    }
     
    /*
    *	Crée, alloue dynamiquement et initialise un élément.
    *	@param value	La valeur de l'élément.
    *	@return 		Si l'allocation réussit, retourne l'élément initialisé
    *					dynamiquement, sinon retourne la valeur NULL.
    */
    Stack initialize(int value)
    {
    	Stack stack = NULL;
    	stack = malloc(sizeof(stack));
     
    	if(stack != NULL)
    	{
    		stack->value = value;
    	}
    	else
    	{
    		perror("Impossible d'allouer dynamiquement un élément");
    	}
    	return stack;
    }
     
    /*
    *	Ajoute un élément dans la pile.
    *	@param stack	Un pointeur de pointeur sur la pile dans laquelle l'élément sera ajouté.
    *	@param value	La valeur à ajouter dans la pile.
    */
    void push(Stack* stack, int value)
    {
    	Stack element = initialize(value);
    	element->next = (*stack);
    	(*stack) = element;
    }
    Voila la ligne de commande avec laquelle je compile:
    valgrind --tool=memcheck --leak-check=full --leak-resolution=high --show-reachable=yes ./integerStack

    Et voila les erreurs:

    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
     
    ==9766== Invalid write of size 4
    ==9766==    at 0x80484EC: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==  Address 0x418502c is 0 bytes after a block of size 4 alloc'd
    ==9766==    at 0x4022AB8: malloc (vg_replace_malloc.c:207)
    ==9766==    by 0x80484AB: initialize (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x80484E0: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766== 
    ==9766== Invalid read of size 4
    ==9766==    at 0x80485C7: printStack (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x8048479: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==  Address 0x418502c is 0 bytes after a block of size 4 alloc'd
    ==9766==    at 0x4022AB8: malloc (vg_replace_malloc.c:207)
    ==9766==    by 0x80484AB: initialize (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x80484E0: push (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    ==9766==    by 0x804846E: main (in /media/KINGSTON/Cours/CoursAlgo/CM/integerStack)
    Quelqu'un pourrait-il m'expliquer le problème


    ET l'erreur
    Ben le problème c'est que ton code est incompréhensible sauf pour toi (ou alors faut l'examiner plus en détail)
    1) tu utilises un type "stack" qui masque une étoile puis tu passes à ta fonction push() l'adresse de stack qui sera donc un double étoile. Je sais même pas si le pointeur initial a été alloué avant de remplir son contenu (ça doit sûrement se savoir si on examine le code plus en détail mais si un code de 50 lignes on doit mettre 10mn à le déchiffrer c'est qu'il est déjà mal écrit)

    2) tu utilises un type "stack" et une variable "Stack" (ou l'inverse je sais plus). Tu veux pas utiliser en plus une structure sTack histoire qu'on soit encore plus paumés ???

    Donc commence par nommer tes types "t_qqchose". Ne masque pas les étoiles (c'est inutile) et là tout le monde s'en sortira bien plus facilement (et ptet même que t'arriveras à trouver toi-même ton erreur).

    Si tu veux je peux même te dire comment j'aurais défini mes objets
    1) une structure "s_element" qui contient ma data et le next
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct s_element {
    	int value;				// Le contenu de la liste chainée
    	struct s_element *next;	// L'élément suivant de la liste chainée.
    } t_element;
    2) une structure "s_stack" qui contient le premier pointeur vers s_element. Cette seconde structure peut sembler inutile vu qu'elle ne contient qu'un truc mais l'avantage, c'est que si demain tu veux rajouter d'autres choses comme par exemple le nombre d'éléments, ou alors la mémorisation de l'élément en cours, te suffit de le rajouter simplement dans cette structure et les modif sont minimes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef struct {
    	t_element *first;			// Le premier élément
    } t_stack;

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 123
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ben le problème c'est que ton code est incompréhensible sauf pour toi (ou alors faut l'examiner plus en détail)
    1) tu utilises un type "stack" qui masque une étoile puis tu passes à ta fonction push() l'adresse de stack qui sera donc un double étoile. Je sais même pas si le pointeur initial a été alloué avant de remplir son contenu (ça doit sûrement se savoir si on examine le code plus en détail mais si un code de 50 lignes on doit mettre 10mn à le déchiffrer c'est qu'il est déjà mal écrit)

    2) tu utilises un type "stack" et une variable "Stack" (ou l'inverse je sais plus). Tu veux pas utiliser en plus une structure sTack histoire qu'on soit encore plus paumés ???

    Donc commence par nommer tes types "t_qqchose". Ne masque pas les étoiles (c'est inutile) et là tout le monde s'en sortira bien plus facilement (et ptet même que t'arriveras à trouver toi-même ton erreur).

    Si tu veux je peux même te dire comment j'aurais défini mes objets
    1) une structure "s_element" qui contient ma data et le next
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct s_element {
    	int value;				// Le contenu de la liste chainée
    	struct s_element *next;	// L'élément suivant de la liste chainée.
    } t_element;
    2) une structure "s_stack" qui contient le premier pointeur vers s_element. Cette seconde structure peut sembler inutile vu qu'elle ne contient qu'un truc mais l'avantage, c'est que si demain tu veux rajouter d'autres choses comme par exemple le nombre d'éléments, ou alors la mémorisation de l'élément en cours, te suffit de le rajouter simplement dans cette structure et les modif sont minimes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef struct {
    	t_element *first;			// Le premier élément
    } t_stack;
    Voila le code remanié tel-que conseillé. Je n'ai pas utilisé ta deuxième structure car je fais un exercice pour la fac et ce n'est pas demandé.

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    /*
    *	Element de la pile.
    */
     
    typedef struct s_element 
    {
    	int value;				// Le contenu de l'element
    	struct s_element *next;	// L'élément suivant de la pile.
    }t_element;
     
    t_element* initialize(int value);
    void push(t_element** stack, int value);
     
    int main(void)
    {	
    	t_element* pt_stack = NULL;	// Pointeur sur la pile
    	push(&pt_stack, 0);			// Ajout d'un élément dasn la pile
    	free(pt_stack);				// Liberation de l'unique élément dans la pile. 
    	return 0;
    }
     
    /*
    *	Crée, alloue dynamiquement et initialise un élément.
    *	@param value	La valeur de l'élément.
    *	@return 		Si l'allocation réussit, retourne l'élément initialisé
    *					dynamiquement, sinon retourne la valeur NULL.
    */
    t_element* initialize(int value)
    {
    	t_element* element = NULL;
    	element = malloc(sizeof(element));
     
    	if(element != NULL)
    	{
    		element->value = value;
    	}
    	else
    	{
    		perror("Impossible d'allouer dynamiquement un élément");
    	}
    	return element;
    }
     
    /*
    *	Ajoute un élément dans la pile.
    *	@param element	Un pointeur de pointeur sur la pile dans laquelle l'élément sera ajouté.
    *	@param value	La valeur à ajouter dans la pile.
    */
    void push(t_element** stack, int value)
    {
    	t_element* element = initialize(value);		// Création d'un élément
    	element->next = (*stack);					// L'élément pointe sur la pile
    	(*stack) = element;							// La pile pointe sur l'élément nouvellement ajouté
    }
    Pour répondre à ta question 1 le pointeur sur la pile n'est pas alloué quand j'appelle la fonction push:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	t_element* pt_stack = NULL;	// Pointeur sur la pile
    	push(&pt_stack, 0);			// Ajout d'un élément dans la pile
    La fonction push a pour but de stocker la valeur 0 dans la pile. Elle crée donc un élément par l'appel à la fonction t_element* initialize(int value);

    Merci de tes réponses

  4. #4
    Membre confirmé

    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2005
    Messages : 464
    Points : 646
    Points
    646
    Par défaut
    Tu fais une erreur ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stack = malloc(sizeof(stack));
    stack est ton pointeur, tu veux faire probablement une allocation de la taille de la structure donc *Stack.

    Valigrind te dit donc que tu essaies d'écrire vers une adresse non allouée (à cause du malloc() d'une taille insuffisante).

    Cela dit, je n'utilise jamais de typedef pour des pointeurs pour éviter ces confusions.
    ++

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 123
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par bizulk Voir le message
    Tu fais une erreur ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stack = malloc(sizeof(stack));
    stack est ton pointeur, tu veux faire probablement une allocation de la taille de la structure donc *Stack.

    Valigrind te dit donc que tu essaies d'écrire vers une adresse non allouée (à cause du malloc() d'une taille insuffisante).

    Cela dit, je n'utilise jamais de typedef pour des pointeurs pour éviter ces confusions.
    ++
    Je ne peux pas tester tout de suite mais ça doit être ça.

    Merci beaucoup.
    Je ne suis pas non plus trop fan du typedef pour des pointeurs mais le prof n'utilise que ça et si je luis dis que ce qu'il fait c'est de la merde il ne va surement pas être content

    Je test se soir et met en résolu si c'est bon .

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 739
    Points : 31 068
    Points
    31 068
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bizulk Voir le message
    Tu fais une erreur ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stack = malloc(sizeof(stack));
    stack est ton pointeur, tu veux faire probablement une allocation de la taille de la structure donc *Stack.
    Hum ça j'aurais dû le voir

    Citation Envoyé par Anonymouse Voir le message
    Je ne suis pas non plus trop fan du typedef pour des pointeurs mais le prof n'utilise que ça et si je luis dis que ce qu'il fait c'est de la merde il ne va surement pas être content
    Il y a plusieurs façons de dire les choses. L'important est de ne jamais être grossier mais de développer des arguments réfléchis. Dans ce cas t'as le droit de défendre tes idées.

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

Discussions similaires

  1. PLS-00103 erreur incomprise sur PL/SQL developer
    Par balkis dans le forum PL/SQL
    Réponses: 5
    Dernier message: 01/09/2010, 17h03
  2. Réponses: 4
    Dernier message: 21/09/2007, 17h37
  3. Erreur incomprise sur le d_type
    Par lowboy dans le forum C
    Réponses: 7
    Dernier message: 22/07/2007, 11h42
  4. [FPDF] erreur incomprise
    Par oceane751 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 17/01/2007, 01h20
  5. Erreur incomprise avec DBI et perl
    Par duedos dans le forum SGBD
    Réponses: 3
    Dernier message: 04/07/2006, 12h43

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