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 :

Gestion de la mémoire avec "realloc"


Sujet :

C

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut Gestion de la mémoire avec "realloc"
    Bonjour à tous,

    Je cherche à comprendre comment fonctionne realloc lorsqu'on a fait un malloc avant.

    Est-ce que si on déclare quelques entiers avant le realloc, l'adresse de l'espace mémoire allouée après avec realloc sera avancé des X entiers déclaré avant !?

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    void main(void)
    {
        int a = 9;
        int nombre = 5;
     
        int * valeurs;
        valeurs = (int *) malloc(sizeof(int) * nombre);
     
        double test = 9.9;
     
    	if ( valeurs == NULL )
    	{
    		fprintf(stderr,"Allocation impossible \n");
    		exit(EXIT_FAILURE);
    	}
    	else
    	{
     
    		*valeurs = 1;
    		printf("%d\n",*valeurs);
     
    		int k[2000];
     
    		valeurs = realloc (valeurs, sizeof(int) * (nombre + 1) );
     
    		printf("%d\n",valeurs[4]);
    		printf("%d\n",valeurs[5]);
     
    		//adresses
    		valeurs++;
    		printf("%p\n",valeurs);
    		valeurs++;
    		printf("%p\n",valeurs);
    		valeurs++;
    		printf("%p\n",valeurs);
    		valeurs++;
    		printf("%p\n",valeurs);
    		valeurs++;
    		printf("%p\n",valeurs);
    		valeurs++;
    		printf("%p\n",valeurs);
     
    		valeurs = valeurs - 6;
     
    		free(valeurs);
    		valeurs=NULL;
     
    	}
     
    }
    J'obtiens cette réponse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    1
    0
    0
    0xf30014
    0xf30018
    0xf3001c
    0xf30020
    0xf30024
    0xf30028 //adresse réalloué du tableau alloué dynamiquement avec malloc
    La dernière adresse devrait être de 0xf30024 + X entiers "int k[2000];" !!

  2. #2
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    pour connaître les spécifications de realloc, le plus simple est d'aller voir la doc: http://www.cplusplus.com/reference/cstdlib/realloc/

    le principe est que realloc agrandit le bloc alloué par malloc; s'il n'y a pas la place de l'agrandir sans le déplacer, le contenu est copié.

    pour ton programme, comme l'adresse de valeur[0] est resté stable, c'est que la réallocation sur place a été possible.

    en revanche le résultat qui t'étonne n'est pas du tout étonnant: si tu prends un pointeur sur une adresse mémoire et que tu l'incrémentes, tu auras la prochaine adresse (selon le type +1, +4 etc. bytes) quelle que soit l'allocation mémoire que tu aies pu faire. L'allocation d'un tableau statique de 2000 int ne change rigoureusement rien à l'affaire (au passage, l'allocation statique se fait dans le segment "data" du programme, avec malloc c'est dans le tas que tu vas piocher)

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Citation Envoyé par stendhal666 Voir le message
    le principe est que realloc agrandit le bloc alloué par malloc; s'il n'y a pas la place de l'agrandir sans le déplacer, le contenu est copié.
    Donc si on fait un malloc à la place des 2000 entiers et si il n'y a pas assez de place pour l'agrandir sans le déplacer, alors il faut copier le contenu et déplacer l'adresse de début du tableau puis agrandir le tableau.

    Cette façon de coder n'est pas très propre, il vaut mieux changer la taille juste après malloc. Avez-vous déjà connu des situations ou vous étiez obligé de faire un realloc bien après dans la suite du programme? (est-ce que la mémoire libéré dans le tas sera à nouveau utilisable?)

    l'allocation statique se fait dans le segment "data" du programme, avec malloc c'est dans le tas que tu vas piocher
    Merci pour ta précision. Je me demande si c'est aussi le cas pour des processeurs ARM par exemple.

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    C'est realloc qui se charge de recopier la mémoire allouée par le malloc initial, ce n'est pas au programmeur de le faire.

    Realloc est utile quand on doit recopier un élément de longueur inconnue: plutôt que d'allouer un très gros bloc et de prier pour qu'il suffise, on tient le compte de ce qui est copié et on realloc quand c'est necessaire. C'est ce qui se passe dans les conteneurs du C++ par exemple.

    Pour donner un exemple en C, la fonction getline qui lit une ligne dans un fichier fonctionne également de cette façon.

    Pour ce qui est des processeurs, cela n'a pas tant d'influence sur la disposition de l'exécutable que le système d'exploitation.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Ce que je conseille pour realloc(), c'est de faire une fonction plus spécifique, avec un retour booléen et un pointeur de pointeur.
    Exemple:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int reallocTableauDouble(double **pp, size_t nouvelleTaille)
    {
    	int ret = 0;
    	double* tmp = realloc(*pp, nouvelleTaille*sizeof(*tmp));
    	if(tmp != NULL)
    	{
    		*pp = tmp;
    		ret = 1;
    	}
    	return ret;
    }
    Avec ça, si le realloc() réussit, le pointeur pointé est modifié (ou non) selon les besoins, et si le realloc() échoue, le pointeur existant n'est pas perdu (pas de fuite de mémoire).

    PS: Un tableau en tant que variable locale sans le mot-clé static est couramment appelé "allocation statique", mais c'est un abus de langage. Il s'agit en fait d'un tableau en allocation dite automatique, sur la pile avec les autres variables locales à la fonction.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Oui c'est vrai que ce n'est pas au programmeur de s'occuper de ça mais j'aime bien savoir ce qui se passe.

    Merci pour l'exemple. En fait, c'est parce qu'on a un pointeur de pointeur que le pointeur p ne sera pas perdu ?

    Pour les débogueurs et pour surveiller si on a pas des fuites de mémoires, on peut utiliser gdb et valgrind. Qu'utilisez-vous pour vous assurer du bon fonctionnement d'un programme en C?

    Merci encore

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    La fonction accepte un pointeur de pointeur pour pouvoir modifier le pointeur.
    Mais en fait, elle sert surtout à éviter un anti-pattern commun dans l'usage de realloc:
    Code mauvais : Sélectionner tout - Visualiser dans une fenêtre à part
    buffer = realloc(buffer, nouvelleTaille); //piège!

    Avec ce mauvais code, si realloc() échoue, on perd le pointeur sur le buffer alors qu'il est toujours alloué -> fuite de mémoire.
    En utilisant une fonction qui passe par une variable intermédiaire (tmp) et ne modifie le pointeur qu'en cas de réussite de realloc(), on évite ce piège.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Merci pour vos réponse.

    Je me demandais comment fournir un code C "safe" pour des applications critiques de manière générale?

    Toujours vérifier que les fonctions disponibles dans les bibliothèques se finissent correctement, comme pour ici ou on pourrait perdre le pointeur !

    Faut-il se servir de stderr par exemple, ...

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Franchement, si on veut écrire du code "safe" pour applications critiques, si on a le choix, on ne l'écrit pas en C. On utiliserait plutôt du C++, qui permet d'écrire du code plus "safe" sans trop sacrifier en performance (à supposer que la performance soit un critère) tout en permettant de faire, au besoin, tout ce que le C permet.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Étonnant comme point de vue mais ça peut se comprendre. Alors du coup le C nous sert-il encore? Le C++ vient du C non?

    Je pense surtout pour de la programmation de processeurs. Le C++ n'est pas fait pour ce type de cible, non?

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Si tu considères "programmation de processeurs" comme voulant dire "programmation directement en assembleur", alors sans extensions, le C ne le supporte pas non-plus: Il n'y a pas de support dans le standard C pour l'assembleur in-line.

    En fait, la plus grosse limitation pour le C++ est que certaines plate-formes supportent un compilateur C mais pas de compilo C++ (et encore, avec un transcompilateur de C++ vers C, le problème peut être contourné).
    Le reste, c'est simplement que si on ne sait pas ce qu'on fait, certaines fonctionnalités du C++ se payent très cher en performance (espace pris en mémoire, indirections supplémentaires, etc.) donc pour du performance-critical, il faut peser le pour et le contre entre performance et sécurité.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 374
    Points : 47
    Points
    47
    Par défaut
    Merci pour cette discussion forte intéressante!

    Bonne après-midi à toi

Discussions similaires

  1. Gestion de la mémoire avec RMS
    Par bpmfoukamoko dans le forum Développement Mobile en Java
    Réponses: 3
    Dernier message: 12/09/2008, 22h14
  2. Gestion de la mémoire avec Firefox
    Par NeqO55 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 24/09/2007, 13h26

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