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 :

erreur en libérant un pointeur ?


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut erreur en libérant un pointeur ?
    Bonjour,

    J'ai le code suivant

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main (void)
    {
      int x=10;
      int *px;
     
      px=malloc(sizeof(int));
      if ( px == NULL )
         return 0;
     
      x=10;
      px=&x;
     
      printf (" la valeur est %d\n",*px);
     
      free(px);
     
    }
    Ca compile puis quand j'exécute, j'ai bien le résultat qui s'affiche (10), mais j'ai aussi l'erreur suivante qui s'affiche *** Error in `./test': free(): invalid pointer: 0x00007ffdf42e0748 ***
    Aborted

    Question 1: Vous savez m'expliquer d'où vient l'erreur ? Pourquoi j'ai un problème en libérant mon pointeur ?
    Question 2: si je voulais afficher l'adresse de x (ca n'a pas forcément d'intéret, c'est juste comme ça) - c'est stocker dans px pour pouvoir pointer sur x, mais je n'arrive pas l'afficher - comment faire ?

    Merci pour votre aide

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 38
    Points : 79
    Points
    79
    Par défaut
    Le malloc et le free ne serve a rien.

    Le malloc te crée un int dans la memoire. Le free libère ce int... sauf que tu liberes x et non le inr crée par malloc

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 38
    Points : 79
    Points
    79
    Par défaut
    Quand je dit ne servent à rien, c'est dans ton cas

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 38
    Points : 79
    Points
    79
    Par défaut
    Pour la question 2, printf de px devrait afgicher l'adresse de x

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut
    Bonjour,
    - pour la question 1 : le malloc et free ne servent à rien parce que je travaille sur un int que j'ai déclaré avant c'est ça? Si j'avais utilisé uniquement des pointeur, il aurait fallu que j'utilise malloc & free ?
    - pour la question 2 : si je fais printf (" px est %d\n",px), ca me fait une erreur de compilation "error: format specifies type 'int' but the argument has type 'int *' [-Werror,-Wformat]". Ma syntaxe est mauvaise ?

  6. #6
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Points : 1 753
    Points
    1 753
    Par défaut
    Bonjour,

    Citation Envoyé par ceimoi Voir le message
    Bonjour,

    J'ai le code suivant

    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
    #include <stdio.h>
    #include <stdlib.h>
    
    int main (void)
    {
      int x=10;
      int *px;
      
      px=malloc(sizeof(int));
      if ( px == NULL )
         return 0;
      
      x=10;
      px=&x;
      
      printf (" la valeur est %d\n",*px);
    
      free(px);
    
    }
    Ca compile puis quand j'exécute, j'ai bien le résultat qui s'affiche (10), mais j'ai aussi l'erreur suivante qui s'affiche *** Error in `./test': free(): invalid pointer: 0x00007ffdf42e0748 ***
    Aborted

    Question 1: Vous savez m'expliquer d'où vient l'erreur ? Pourquoi j'ai un problème en libérant mon pointeur ?
    Question 2: si je voulais afficher l'adresse de x (ca n'a pas forcément d'intéret, c'est juste comme ça) - c'est stocker dans px pour pouvoir pointer sur x, mais je n'arrive pas l'afficher - comment faire ?

    Merci pour votre aide

    Votre erreur, viens du fait que vous avez attribué à la variable pointeur "px" une autre adresse que celle qui a été allouer et comme votre pointeur pointe sur une autre adresse la fonction "free()" ne peut libérer l’espace mémoire assigné (car l'objet pointé n'est pas alloué) générant ainsi une erreur de trap(6) EXC_CRASH (SIGABRT) de plus la mémoire allouée précédemment ne étant pas libérée entraînent en conséquence la où des pertes de mémoire irrécupérables (le programme crée des fuites de mémoires). Pour corriger le problème, il faut déréférencé le pointeur pour qu’il puisse contenir la valeur de la variable "X" comme ceci: *px = x

    Plus de précision: La manipulation des pointeurs se fait de la façon suivante:
    L’opérateur ‘&' permet d’obtenir l’adresse d’une variable de type type exemple: int *p = &x.L’opérateur ‘&' ne peut être appliqué qu’a des variables donc, des objets qui se trouvent uniquement dans la mémoire interne et ne peut pas être utilisés à des variables déclarées avec les mots-clés « register » ou des expressions.
    L’opérateur ‘*’ permet d’accéder à la valeur de l’objet pointé en clair au contenu de l’adresse. Ce procédé est appelé déréférencement de pointeur Exemple:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        int x = 10;
        int *p = &x;
        *p = 19; // change la valeur de x.

    Il est toutefois conseillé de faire attention car, un pointeur est une variable comme toutes les autres donc un pointeur doit être initialisé a « NULL » en attente de données a pointé car, si vous ne le faites pas elle contiendra une valeur aléatoire (sauf cas de static) donc vers une donnée en mémoire quelconque que vous n’avez pas le droit d’accès.

    à l'avenir il faut êtres très vigilants à la manipulation des pointeurs et voici d'autre d'informations qui vous seront très utiles
    à bientôt

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut
    Merci Sambia39 de la réponse détaillée.

    Est ce que le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      int x=10;
      int *px;
      x=10;
      px=&x;  
      printf (" la valeur est %d\n",*px);
    est une utilisation "non conforme" où j'utilise un pointeur que je ne déréférence pas? L'utilisation correcte est avec *px=x ?

    Pour ma 2ieme question : si jamais je veux afficher l'adresse de x - comment faire?
    printf (" la valeur est %d\n",px) ne fonctionne pas car %d attend un int et pas un int* comme px

  8. #8
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 580
    Points : 7 712
    Points
    7 712
    Par défaut
    Citation Envoyé par ceimoi Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      int x=10;
      int *px;
      x=10;
      px=&x;  
      printf (" la valeur est %d\n",*px);
    est une utilisation "non conforme" où j'utilise un pointeur que je ne déréférence pas? L'utilisation correcte est avec *px=x ?
    C'est conforme, le pointeur pointe quelque part (sur x), et il est déréférencé au moment du printf par *px, et il n'y a ni allocation ni dés-allocation dynamique.
    après avoir affecté px, on peut utiliser *px pour lire ou écrire, on pourrait ensuite effectuer *px = x + 1 pour lire 11 dans x.
    Citation Envoyé par ceimoi Voir le message
    Pour ma 2ieme question : si jamais je veux afficher l'adresse de x - comment faire?
    printf (" la valeur est %d\n",px) ne fonctionne pas car %d attend un int et pas un int* comme px
    En effet il faut faire printf(" la valeur du pointeur %n\n" , px ).

    Correctif, merci Sambia, il faut utiliser %p pour le format des pointeurs, surtout pas %n qui sert à tout autre chose.

  9. #9
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Points : 1 753
    Points
    1 753
    Par défaut
    Bonjour,
    Attention, l'instruction proposé est incorrect
    Citation Envoyé par dalfab Voir le message
    printf(" la valeur du pointeur %n\n" , px ).
    Pour affiché l'adresse du pointeur ou d'une variable on utilise le spécificateur de format "%p"
    fprintf("Adresses\t:%p\n", (void*)&x);
    fprintf("Adresses\t;%p\n", px);
    A bientôt

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut
    Merci à tous

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut
    Rebonjour,
    Je croyais avoir compris mais pas complètement...

    Je ne comprends pas pourquoi le code suivant marche et renvoit bien la lettre e:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *mot="hello";
    printf("la valeur est %c", mot[1]);
    moi j'aurais volontier écrit ca, mais le compilateur refuse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *mot="hello";
    printf("la valeur est %c", *mot[1]);
    En mettant *mot[1], j'ai bien accès à la valeur pointée non ?
    Vous pouvez m'expliquer pourquoi mon 2nd cas ne fonctionne pas alors que le 1er oui ?

    Merci

  12. #12
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 580
    Points : 7 712
    Points
    7 712
    Par défaut
    Bonjour,

    Quand on écrit char* mot; on définit un pointeur sur un char.
    Quand on écrit char* mot = "hello"; on donc aussi un pointeur sur un char, il pointe sur le 'h' 1er caractère de la chaîne, 5 autres caractères sont placés ensuite 'e', 'l', 'l', 'o' et '\0'.

    Il existe une règle d'équivalence qui fonctionne aussi bien avec les pointeurs que les noms de tableau :
    pt[i] <=> *(pt+i).
    Accéder au i-ème élément d'un tableau, c'est la même chose que de déréférencer l'ajout d'un pointeur à un offset.

    Dans le premier cas en écrivant mot[1], c'est l'équivalent de *(mot+1) pour accéder au 2nd caractère.
    Dans le second cas en écrivant *mot[1], on déréférence mot[1] qui n'est pas un pointeur.

    Un tableau c'est finalement quasiment la même chose qu'un pointeur qui serait fixé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    tab = ptr;  // n'a pas de sens
    tab = tab2; // n'a pas de sens
    ptr = tab;  // ok et le pointeur pourra être utilisé comme un tableau
    ptr = ptr2; // ok
    sizeof(tab); // c'est la taille du tableau entier
    sizeof(ptr); // c'est toujours la taille d'un pointeur
    // une fonction ne peut pas recevoir si retourner un tableau, il y a conversion systématique en pointeur
    char* fct1( char* tab ); 
    char* fct2( char tab[] ); // notation possible, mais en fait est la même que fct1

  13. #13
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2016
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2016
    Messages : 21
    Points : 9
    Points
    9
    Par défaut
    Merci

  14. #14
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Points : 1 753
    Points
    1 753
    Par défaut
    Bonjours,
    Citation Envoyé par dalfab Voir le message
    Bonjour,

    Quand on écrit char* mot; on définit un pointeur sur un char.
    Quand on écrit char* mot = "hello"; on donc aussi un pointeur sur un char, il pointe sur le 'h' 1er caractère de la chaîne, 5 autres caractères sont placés ensuite 'e', 'l', 'l', 'o' et '\0'.

    Un tableau c'est finalement quasiment la même chose qu'un pointeur qui serait fixé

    Attention dire qu’un "tableau est finalement quasiment la même chose qu’un pointeur qui serait fixé" est totalement incorrecte. Un tableau n’est pas un pointeur et une variable pointeur n’est pas un tableau c’est deux choses bien différentes, mais la manipulation permettant l’accès à l’élément est exactement la même et comme vous l’avez mentionné il existe quelques différences et incompatibilités comme l’utilisation de sizeof qui ne renvoie pas le même résultat. Sur un tableau la fonction renvoie la taille du tableau c'est-à-dire le nombre d’éléments du tableau fois la taille d’un élément. Dans le cas du pointeur c’est la taille d’un pointeur et leur espace mémoire réservé n’est pas le même (dû a leur code machine différente) et l’éditeur de liens n’a pas la même correspondance, car il apparaît différemment (ce qui est tout à fait compréhensible cela permet à l’éditeur de liens de s’y retrouver) .
    Exemple: (source.h & source.c)

    Code C : 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
     
    /*
     ============================================================================
     Name        : source.h
     Author      : SAMBIA39
     Version     : 0.1
     Copyright   : Copyright (c) 28/12/2016 SAMBIA39
     Description : Ansi-style
     ============================================================================
     */
     
    #ifndef DEF_SOURCE_H
    #define DEF_SOURCE_H
     
    #include <stdio.h>
    #include <stdlib.h>
     
    short tableaux[5] = { 0, 1, 2, 3, 4 }; //Tableaux 
     
    #endif

    Code C : 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
    /*
     ============================================================================
     Name        : source.c
     Author      : SAMBIA39
     Version     : 0.1
     Copyright   : Copyright (c) 28/12/2016 SAMBIA39
     Description : Ansi-style
     ============================================================================
     */
    
    #include "source.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    int main( void ){
    	
    	unsigned short i = 0;
    	extern short *tableaux;   // ERREUR compilation car tableau n'est pas un pointeur
    	
    	for( i = 0; i < 5; i++ )
    		fprintf( stdout, "%d\t", tableaux[i] );
    	fprintf( stdout, "\n" );
    	
    	return EXIT_SUCCESS;
    }

    Si "tableaux" est un tableau alors le compilateur connaîtra sa place à la compilation et le remplace par le code machine, mais pas un pointeur, car il devra être déférence lors de l’exécution du programme. Voici un autre exemple qui montre que la différence entre variables pointeur et tableau est importante (totalement différente)
    Code C : 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
     
    /*
     ============================================================================
     Name        : source.c
     Author      : SAMBIA39
     Version     : 0.1
     Copyright   : Copyright (c) 28/12/2016 SAMBIA39
     Description : Ansi-style
     ============================================================================
     */
     
    #include "source.h"
    #include <stdio.h>
    #include <stdlib.h>
     
    int main( void ){
     
    	unsigned int i = 0;
    	char *ptr = "Bonjours\0";      // Pointeur sur chaîne constant
     
    	//Affichage
    	for( i = 0; i < 8; i++ )
    		fprintf( stdout, "%c", ptr[i] );
    	fprintf( stdout, "\n" );
     
    	/*
    	* Les instructions qui vont suivrent génère lors de l'excusion un 
    	* «Terminated due to signal: BUS ERROR (10)» qui clairement veut dire impossibles de manipuler 
    	* un pointeur sur une chaîne constante. Pour le faire il faut non pas déclarer une variable 
    	* pointeur sur chaîne constante, mais utiliser un tableau préalablement allouer (dynamiquement)
    	* de la mémoire pour la chaîne de caractères pour pouvoir manipuler la chaîne par la fonction 
    	* d’allocation mémoire "malloc" ou à travers les VLA du C99.
    	*/
    	for( i = 0; i < 8; i++ )
    		ptr[i] = 'A';
     
    	//Affichage
    	for( i = 0; i < 8; i++ )
    		fprintf( stdout, "%c", ptr[i] );
    	fprintf( stdout, "\n" );
     
    	return EXIT_SUCCESS;
    }
    « ptr » est un pointeur sur une chaîne constante et le compilateur peut tout à fait placer la chaîne constante dans un segment de données en lecture seule et toute tentative de modification à travers un pointeur aboutira systématiquement à une erreur de segmentation.

    En résumé: Un pointeur (variable pointeur) n’est pas un tableau et un tableau n’est pas un pointeur, mais l’accès à l’élément est identique. Cette même logique s’applique également avec les pointeurs et tableaux à plusieurs dimensions, mais l’un des avantages des pointeurs qu’il faut reconnaître sur des tableaux multidimensionnels est principalement la possibilité de créé des vecteurs dits d’Ilife qui sont des lignes de tableaux d'i de différentes tailles (ptr_tab[i]) chose qu’un tableau ne peut faire.

    à bientôt

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

Discussions similaires

  1. Erreur étonnante à propos des pointeurs!
    Par dingua dans le forum Débuter
    Réponses: 17
    Dernier message: 21/12/2009, 11h10
  2. Erreur à rallonge sur les pointeurs.
    Par barbug dans le forum Débuter
    Réponses: 6
    Dernier message: 22/12/2008, 17h09
  3. Erreur de manipulation de pointeur
    Par Bleys dans le forum Langage
    Réponses: 0
    Dernier message: 05/08/2008, 09h24
  4. Erreurs de compilation des pointeurs
    Par hanry dans le forum Débuter
    Réponses: 7
    Dernier message: 18/03/2008, 14h34
  5. erreur 2397 : problème de pointeurs
    Par klair dans le forum Delphi
    Réponses: 5
    Dernier message: 29/05/2006, 11h55

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