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 :

Malloc : anomalie d'assignation de pointeur


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Par défaut Malloc : anomalie d'assignation de pointeur
    Bonjour,

    Je suis sur mac et je compile dans l'invit de commande avec le compilateur de Xcode.
    J'ai abordé les pointeurs récemment et j'ai rencontré des problèmes étranges.
    J'ai créé une fonction simple pour vous illustrer le problème; quand j'alloue dans une fonction un pointeur, celui-ci n'a pas la même adresse quand je sors dans ma fonction.
    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    int test(int* pntr)
    {
    	pntr = malloc(sizeof(int));
    	*pntr = 34;
    	printf("\n%p\n%d", pntr, *pntr);
    	return 0;
    }
     
    int main()
    {
    	int* pntr;
    	test(pntr);
    	printf("\n%p\n%d", pntr, *pntr);
    	free(pntr);
    }
    Et voici le résultat compilé ainsi que le message d'erreur sur le terminal:

    0x7f8be2c04be0
    34
    0x7fff62a93036
    az.sh(771,0x7fff7f62d300) malloc: *** error for object 0x7fff62a93036: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
    -125990072Abort trap: 6

    J'obtiens deux adresses mémoires différentes…
    J'ai soumis le problème à mon prof de C qui n'a pas trouvé et a un moment pensé qu'il y avait un garbage collector mais dans un compilateur de C c'est absurde.. Je suis perdu et sans solutions.
    Merci de votre aide,
    Cordialement.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Cela est, à mon sens, normal.
    Je préviens par avance, je suis moi-même étudiant, donc ce que je vais répondre est " ce qu'il me semble " être. Je ne garantis pas que cela soit la vérité.

    Dans un premier temps, tu déclares un pointeur *pntr qui pointera vers une zone mémoire indéfinie mais réel.
    Tu passes le pointeur comme paramètre de ta fonction.

    Il faut bien comprendre que, dans une fonction, tout ce qui est "autour de lui", n'existe pas. Et l'inverse est vrai aussi. Un programme appelant une fonction n'a pas de droit de regard sur ce qu'il se passe à l'intérieur de celle-ci. Il demande juste l'exécution d'une fonction, et attends ou non une valeur de retour. Le reste, et bien... ça ne nous.. regarde pas.

    Dans ta fonction, quand tu fais pntr = malloc(sizeof(int));, il allouera une zone mémoire, et aura donc une adresse pointant vers cette zone mémoire.
    SAUF QUE, dans les paramètres de ta fonction, tu précises bien que tu passes un pointeur. Un pointeur est avant tout une adresse. Si tu changes l'adresse pointé en cours d'exécution, cela se fera localement, le temps de la fonction. Mais le programme principale, lui, ne sait pas que l'adresse à été changé, ni qu'une zone mémoire à été alloué.

    Tu fais ton traitement, toussa toussa.. Tu reviens sur le programme principale qui, comme je l'ai dis, ne sait pas que la mémoire a été alloué par un autre, et gardera donc l'adresse qu'il utilisait lui car tout ce qui se passe dans une fonction ne le regarde pas. Quand tu lui demandes de faire un free(pntr); , il se demande qu'elle mouche te pique et t'envoie sur les roses.

    Pour faire selon ton idée, je pense qu'il faut utiliser une pointeur de pointeur, c'est à dire un pointeur contenant l'adresse d'un autre pointeur..
    Ou alors, "simplement", dans ta fonction, retourner l'adresse qui a été alloué.

    Mais, plus généralement, on évite surtout de faire des malloc dans une fonction, car comme je l'ai dis, ce qui se fait dans une fonction, reste dans une fonction. Si tu alloues dans la fonction, tu dois désalloué dans ta fonction.

    Donc voilà ce que j'en pense, personnellement, sous réserve des commentaires des " pro ", comme on dit.


    ( au passage, un garbage collector en C ..... Quoique... Quand on utilise le free en cours d'exécution, c'est pour laisser la place aux autres données du programme. Si à chaque fois, on alloue un espace mémoire sans de désalloué, au bout d'un moment il n'y aura plus de place et le programme se plantera. Mais; quand on coupe le programme, il me semble que dans mes souvenirs il y a quelque chose qui passe derrière pour désalloué tout ce qui doit l'être. Mais je n'en suis pas sur et il faut que je vérifie sur le coup. )
    Dernière modification par Invité ; 22/11/2014 à 09h50.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Par défaut
    Bonjour,

    Merci bien pour ta réponse, en synthétisant je ne peux qu'allouer une place réservée avec 'malloc' seulement au moment de la déclaration de mon pointeur.
    J'ai testé et cela marche. (encore heureux!)

    Merci pour ton explication claire, je pensais que l'on pouvait en quelque sorte changer l'adresse d'un pointeur sans avoir de problème de local dans une fonction car c'était justement un pointeur.

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pour compléter ce que dit archMqx. il faut bien avoir en tête que les arguments d'une fonction sont toujours en C transmis par valeur. Cela signifie que au moment de l'activation d'une fonction :

    1- il y a création d'un objet local dont le type correspond à celui du paramètre et dont l'identificateur est celui du paramètre. En cela, c'est le même processus que pour toutes les variables locales (déclarées à l'intérieur de la fonction et non static)

    2- cet objet est initialisé par la valeur passée en argument. On obtient donc une copie de cette valeur. Il n'y a ensuite plus aucun lien entre les arguments de la fonction et ses paramètres.

    3- Comme pour toute variable locale, l'objet est détruit en fin de la fonction.

    -------------
    Dans ton programme,

    -main- Dans main() tu as créé un objet pntr. Cet objet n'a pas été initialisé et contient n'importe quoi.
    -main- Tu appelles la fonction test avec cet objet en argument.Alors dans test()

    -main-test- 1 Un objet local, qui s'appelle aussi pntr mais qui est un autre objet, est créé.
    -main-test- 2 Il est initialisé avec la valeur en argument qui est la valeur du pntr du main() autrement dit n'importe quoi
    -main-test- Cette valeur est écrasée par le malloc(), ce qui montre entre parenthèses que ce paramètre n'est pas pertinent puisqu'on n'a jamais utilisé la valeur transmise lors de l'appel
    -main-test- 3 On fait quelques bricoles puis l'objet pntr de test() est détruit lorsqu'on sort de la fonction pour retourner au main()

    -main- au retour, rien n'a changé dans main()
    ------------------

    On a deux possibilités pour qu'une fonction modifie quelque chose dans le programme appelant (en excluant les variables globales qui sont des pestes)
    -1 Utiliser, dans le programme appelant la valeur de retour de la fonction
    -2 Passer à la fonction l'adresse de l'objet qui doit être modifié. La fonction peut alors procéder à la modification de cet objet puiqu'elle sait où il est.

    Dans ton cas et en utilisant la deuxième possibilité, on aurait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
    	int* pntr;
    	test(&pntr); // ici l'adresse de pntr est passée
    	printf("\n%p\n%d", pntr, *pntr);
    	free(pntr);
    }
    A toi de modifier la fonction test() en conséquence.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Je n'aurais pas mieux dit, Diogène.

  6. #6
    Membre Expert
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Par défaut
    Citation Envoyé par archMqx.
    il y a quelque chose qui passe derrière pour désalloué tout ce qui doit l'être. Mais je n'en suis pas sur et il faut que je vérifie sur le coup.
    Effectivement, les OS modernes détruisent le processus quand celui-ci se termine (y compris son espace mémoire, les handles de ses fichiers ouverts, etc...). Mais bon ça reste une bonne habitude de free() quand on a plus besoin d'une zone mémoire allouée par malloc

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Par défaut
    Merci bien à vous tous et à votre rapidité de réponse !
    Cela me fait plaisir

    Bonne continuation !

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 01/11/2010, 19h26
  2. Assignation double pointeur
    Par micromich dans le forum Débuter
    Réponses: 2
    Dernier message: 14/09/2008, 14h03
  3. Réponses: 3
    Dernier message: 17/03/2008, 10h54
  4. assigner un tableau 2D sur un pointeur
    Par ded jay dans le forum C++
    Réponses: 16
    Dernier message: 05/07/2007, 14h40
  5. question sur pointeur retourné par malloc()
    Par gauguin dans le forum C
    Réponses: 8
    Dernier message: 21/02/2007, 18h34

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