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 :

Comment fonctionnent les allocations précisément ?


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut Comment fonctionnent les allocations précisément ?
    Bonjour;bonsoir


    J'aimerais avoir une explication sur l'utilisation des fonctions malloc/calloc/realloc et peut être d'autre s'il en existe d'autre^^

    J'ai lu les informations que me donne mon linux en faisant un man; mais des exemples ne serait pas de refus pour illustrer tout ça.


    D’après ce que j'ai compris la seule différence entre calloc et malloc c'est que lors du malloc on doit utiliser un memset. (Si je traduis avec mon misérable anglais; ça veut donc dire que malloc on lui dit à partir de quel endroit dans la mémoire on doit allouer de l'espace ?)
    Je n'ai jamais vu d'utilisation de ce fameux memset d'où le fait que je galère à comprendre.


    Je suis amené à manipuler ces fonctions dans un tp; et je voudrais bien comprendre leur fonctionnement.


    Par exemple; admettons que l'on est un tableau déclaré sous forme de pointeur; un tableau dynamique donc.


    Pour allouer de la mémoire j'ai réalisé un calloc comme ceci: t étant du type du tableau.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    t=calloc(5 , sizeof(int));
    Donc on aura l'équivalent d'un tableau t[5] sur lequel on peut travailler; affecter des valeurs ou autres.

    Maintenant, admettons que ce tableau de taille 5 soit plein et que je veuille augmenter sa mémoire à nouveau c'est à dire passer de t[5] à t[8] par exemple.
    Comment dois je procéder ? Je suppose que c'est là que le realloc entre en jeu ?



    Ça, c'était pour la partir logistique.


    J'aimerais bien également comprendre comment ces allocations se font au niveau architecture; mais ça c'est encore autre chose.


    Merci pour votre aide !

  2. #2
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par Amnael Voir le message
    Si je traduis avec mon misérable anglais; ça veut donc dire que malloc on lui dit à partir de quel endroit dans la mémoire on doit allouer de l'espace ?
    Non, on ne dit pas à malloc ou calloc partir de quel endroit on veut que la mémoire soit allouée, ce sont malloc ou calloc qui décident de cet endroit. La seule différence entre malloc et calloc, c'est que le contenu de la mémoire retournée par malloc est imprévisible alors qu'avec calloc, la mémoire est remplie de "zéros", ce qui correspond à 0 pour les types numériques entiers ou flottants, à des pointeurs nuls pour les types pointeur, et à des chaines vides pour les chaines de caractères. Il n'est donc pas nécessaire d'initialiser les élements quand on a utilisé calloc, on peut les lire directement alors qu'avec malloc, lire un élement du tableau sans l'avoir initialisé au préalable retourne une valeur indéterminée, et entraîne éventuellement le crash du programme s'il s'agit de pointeurs.

    Maintenant, admettons que ce tableau de taille 5 soit plein et que je veuille augmenter sa mémoire à nouveau c'est à dire passer de t[5] à t[8] par exemple.
    Comment dois je procéder ? Je suppose que c'est là que le realloc entre en jeu ?
    Exactement, tu dois utiliser realloc pour "agrandir" la zone mémoire allouée.

    J'aimerais bien également comprendre comment ces allocations se font au niveau architecture; mais ça c'est encore autre chose.
    Il y a plusieurs façons de procéder suivant les bibliothèques, choix d'implémentations, taille à allouer, etc.

    L'allocation se fait traditionnellement dans le "heap" mais peut aussi utiliser "mmap", ce qui permet de rendre à l'OS la mémoire libérée après un free.
    ɹǝsn *sıɹɐlos*

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Amnael Voir le message
    Bonjour;bonsoir


    J'aimerais avoir une explication sur l'utilisation des fonctions malloc/calloc/realloc et peut être d'autre s'il en existe d'autre^^

    J'ai lu les informations que me donne mon linux en faisant un man; mais des exemples ne serait pas de refus pour illustrer tout ça.


    D’après ce que j'ai compris la seule différence entre calloc et malloc c'est que lors du malloc on doit utiliser un memset. (Si je traduis avec mon misérable anglais; ça veut donc dire que malloc on lui dit à partir de quel endroit dans la mémoire on doit allouer de l'espace ?)
    Je n'ai jamais vu d'utilisation de ce fameux memset d'où le fait que je galère à comprendre.
    ...
    Bonjour.

    Je l'utilise pour la création d'images. J'alloue un espace avec calloc();. Cet espace est un buffer image dans lequel "je dessine". Cet espace n'est libéré qu'à la fin du programme. Donc lorsque j'ai besoin de l'effacer il me suffit de faire un memset(); dessus .

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Il n'y a pas besoin de comprendre en profondeur ce que font malloc/calloc ou autre pour pouvoir les utiliser convenablement. La réponse de jlliagre est correct. Je souhaitais juste préciser une chose :
    malloc,calloc,realloc,free, sont des appels systèmes. Cela veut dire qu'à un moment ou un autre de leur exécution, ils vont parler avec le système (le noyau) et il faut savoir que parler avec le noyau, cela prend un temps un peu plus grand, que les simples fonctions du C (non systèmes, comme sqrt, par exemple). Pour le moment, vous n'en avez que faire, du temps que cela prend, mais il faut le savoir pour plus tard (et lors de développement de programme réactif).

    Maintenant, qu'est ce qu'elle font ?

    Simplement, prenons malloc (calloc, c'est schématiquement la même chose avec un memset en plus (pour mettre la mémoire à zéro), realloc, c'est un malloc spécial, qui peut faire aussi un memcpy).
    Malloc dit :
    "Bonjour Monsieur le système, j'ai besoin de N octets"
    Le système, qui est une sorte de vieux barbu très strict et ordonné va voir dans son index permettant de savoir ce qu'il a en mémoire, si a la place et donc, s'il peut répondre à la demande. Si oui, il retourne un pointeur pour indiquer l'emplacement de la mémoire utilisable. Si non, il retourne NULL (ou il tue le programme (ouep, c'est un vieux barbu aigri))
    En théorie, on a la mémoire, le programme peut continuer tranquillement.

    Pour le free, c'est :
    "Bonjour Monsieur le système, voici la mémoire que vous m'aviez donné, j'en ai plus besoin".
    "Le système dit ok, et on continue le programme"

    Maintenant, j'ai parlé d'un index, qui trace les allocations et utilisations de la mémoire. Cet index existe vraiment et est géré par le système. En soit, c'est souvent une liste chainées, qui traque toutes les allocations. Pour chaque allocation, on sauvegarde l'emplacement en mémoire de la zone alloué, la taille, et surement le système garde aussi un identifiant pour connaître le propriétaire. (Ce qui permettra, lorsqu'un autre programme essaie d'accéder à une zone mémoire qui n'est pas à lui, de lui faire une erreur de segmentation). Après, il existe des algorithmes plus ou moins poussé, qui permettent de gérer les allocations (où les placer, comment utiliser la mémoire finalement libérée et comment gérer la fragmentation).

    Voilà, un peu plus en détails, mais c'est détails sont optionnels. Il faut juste comprendre que malloc demande de la mémoire au système et free, la libère. Un bon programme est un programme qui libère toute la mémoire qu'il a pris, c'est pour ça qu'une règle est de dire : pour un malloc, il faut faire un free.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Merci à tous pour ces précieuses informations je pense avoir bien compris leur fonctionnement à présent.
    AU pire je redemanderais au monsieur barbu de se décrire plus tard



    Malgré tout, il me semble que beaucoup de gens néglige l'aspect architectural d'un ordinateur.

    Je veux dire par là; c'est très bien de savoir que lorsqu'on crée une variable x à laquelle on donne une valeur; cette variable est stocké dans une adresse en mémoire. Mais je pense que ce qui fait la différence entre un programmeur du dimanche et un véritable programmeur concepteur qui comprend ce qu'il fait c'est justement le mécanisme machine; comment le système décide d'allouer telle case mémoire plutôt qu'une autre; comment cela se passe au niveau des composants physiques etc etc

    Je ne dis pas qu'au jours d'aujourd'hui je suis capable de comprendre tout ça; mais je pense que le programme de L2 à la fac essaie de nous sensibiliser sur ces thématiques et pour moi c'est plutôt positif !!!


    Merci encore pour vos réponses.


    EDIT: j'avais oublié un aspect syntaxique qui me turlupine

    Voici ce que l'on trouve dans le cours sur ces fonctions sur developpez.
    J'ai placé un commentaire sur la ligne du calloc
    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
     
    int * tabentier;
    /* Création d'un tableau de 3 entiers */
    tabentier = calloc ( 3 , sizeof(int) ); // parfois je vois ce genre d'allocation se faire de cette façon et je ne comprends pas ce qu'elle veut dire tabentier =(tabentier) calloc ( 3 , sizeof(int) );
     
    tabentier[0] = 1;
    tabentier[1] = 2;
    tabentier[2] = 3;
     
    /* Ajout d'un element au tableau */
    tabentier = realloc (tabentier, 4 * sizeof(int) );
     
    tabentier[3] = 4;
     
    for ( i = 0 ; i < 3 ; i++ )
    {
         printf(" tabentier[%d] = %d \n", i , tabentier[i] );
    }

  6. #6
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tabentier = realloc (tabentier, 4 * sizeof(int) );
    Il faut juste faire attention à ce genre d'utilisation avec realloc. Ce genre d'utilisation n'est pas très recommandée car si realloc échoue pour une quelconque raison, tu perds le pointeur vers ton tableau car realloc renvoie NULL. Il est préférable d'utiliser un pointeur temporaire que tu test pour récupérer le retour de realloc et si realloc réussi alors tu fais une simple affectation entre ton pointeur et le pointeur temporaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tmp = realloc (tabentier, 4 * sizeof(int) );
    if (tmp != NULL)
       tabentier = tmp;
    Bien sûr, ne va pas faire une free sur tmp car sinon tu supprimes ton tableau Fait également toujours des tests de retour de ces fonctions ce que tu ne fais pas à ce que je vois !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Amnael Voir le message
    D’après ce que j'ai compris la seule différence entre calloc et malloc c'est que lors du malloc on doit utiliser un memset
    Salut
    On "doit" pas forcément utiliser memset. La seule règle universelle (valable aussi avec les variables simples) c'est qu'on doit toujours écrire au-moins une fois avant de lire. Donc si t'es certain de remplir ta zone avant de lire son contenu, memset() est inutile...

    Citation Envoyé par Amnael Voir le message
    Je n'ai jamais vu d'utilisation de ce fameux memset d'où le fait que je galère à comprendre.
    memset(zone, octet, taille) => remplira la zone de l'octet marqué sur la taille demandée

    Citation Envoyé par Amnael Voir le message
    Par exemple; admettons que l'on est un tableau déclaré sous forme de pointeur; un tableau dynamique donc.

    int tab*

    Pour allouer de la mémoire j'ai réalisé un calloc comme ceci: t étant du type du tableau.

    t=calloc(5 , sizeof(int));

    Donc on aura l'équivalent d'un tableau t[5] sur lequel on peut travailler; affecter des valeurs ou autres.
    Exact. Toutefois malloc/calloc ne se justifient vraiment que si tu ne connais pas la taille à l'avance quand le tu écris le programme.

    Citation Envoyé par Amnael Voir le message
    Maintenant, admettons que ce tableau de taille 5 soit plein et que je veuille augmenter sa mémoire à nouveau c'est à dire passer de t[5] à t[8] par exemple.
    Comment dois je procéder ? Je suppose que c'est là que le realloc entre en jeu ?
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    t=realloc(t, 8 * sizeof(int))
    C'est la règle de base. Mais il est important de savoir que realloc peut échouer. Et dans ce cas, tu as perdu la zone initiale.
    C'est pour ça qu'on passe généralement par un pointeur temporaire permettant de ne pas perdre t
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int *tmp;
    tmp=realloc(t, 8 * sizeof(int))
    if (tmp == NULL)
    {
    	// Problème realloc - Ici il faut gérer le cas mais heureusement on a toujours t - Généralement on le libère et on quitte
    	free(t);
    	return // Code d'erreur
    }
    // Ici on sait que tmp a été correctement agrandi - On peut le remettre dans t
    t=tmp;

    Citation Envoyé par Amnael Voir le message
    Malgré tout, il me semble que beaucoup de gens néglige l'aspect architectural d'un ordinateur.
    Moi il me semble que beaucoup de gens négligent l'orthographe...

    Citation Envoyé par Amnael Voir le message
    Je veux dire par là; c'est très bien de savoir que lorsqu'on crée une variable x à laquelle on donne une valeur; cette variable est stockée dans une adresse en mémoire. Mais je pense que ce qui fait la différence entre un programmeur du dimanche et un véritable programmeur concepteur qui comprend ce qu'il fait c'est justement le mécanisme machine; comment le système décide d'allouer telle case mémoire plutôt qu'une autre; comment cela se passe au niveau des composants physiques etc etc
    Bon ben alors je suis un programmeur du dimanche...

    Citation Envoyé par Amnael Voir le message
    Voici ce que l'on trouve dans le cours sur ces fonctions sur developpez.
    J'ai placé un commentaire sur la ligne du calloc
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int * tabentier;
    /* Création d'un tableau de 3 entiers */
    tabentier = calloc ( 3 , sizeof(int) ); // parfois je vois ce genre d'allocation se faire de cette façon et je ne comprends pas ce qu'elle veut dire tabentier =(tabentier) calloc ( 3 , sizeof(int) );
    Si c'est vraiment écrit comme ça alors je ne sais pas ce que ça veut dire. Mais je pense que tu t'es trompé et voulait dire tabentier =(int*) calloc ( 3 , sizeof(int) );.
    Ca date du C d'avant. A l'époque où le pointeur universel "void*" n'existait pas, malloc/realloc/calloc étaient du type "char*" (pointeur sur la plus petite entité manipulable au niveau adresse dans une philosophie "la mémoire ne contient en final que de l'octet donc du char").
    Or pour ne pas avoir d'avertissement du compilateur, si on voulait stocker l'adresse d'un char dans un pointeur sur int, il était alors nécessaire de le caster. Au final c'est la même chose. Si malloc a renvoyé l'adresse 0x1010 ça reste une adresse. Simplement le compilo sait que 0x1010 correspond à un caractère (donc si on lui demande son contenu il ne récupèrera que cette case). Avec le cast, on lui dit "maintenant 0x1010 c'est l'adresse d'un entier donc si tu veux son contenu il te faudra récupérer deux (ou 4 ça dépend de l'architecture) cases". A mon avis, c'est ça qui fait la différence entre un programmeur du dimanche et un véritable programmeur concepteur qui comprend non pas ce qu'il fait mais ce qu'il se passe...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Moi il me semble que beaucoup de gens négligent l'orthographe...
    Mea culpa

    Bon ben alors je suis un programmeur du dimanche...
    C'est simplement la façon dont on nous as présenté les choses à la fac;mais ce que tu vient de dire me semble tout a fait crédible

    Si c'est vraiment écrit comme ça alors je ne sais pas ce que ça veut dire. Mais je pense que tu t'es trompé et voulait dire tabentier =(int*) calloc ( 3 , sizeof(int) );
    oui, l'erreur vient de moi.

    A priori, si cela revient au même on peut s'en passer donc.


    Merci pour toutes ces informations !


    Dans mon cas je ne vais pas passer par un pointeur temporaire sur le realloc; on considère que si la ré-allocation plante le programme s'arrête.

    ============================

    Je change totalement de sujet pour le coup; on a également quelques primitives systèmes en C permettant d’obtenir le pid d'un processus; ainsi que de créer des processus avec fork()

    Ma question parait bête mais lorsque l'on utile fork pour créer un processus fils d'un processus père. Que fait le processus ?

    Je pensais que l'utilisation d'une fonction dans un programme était considérer comme un processus en soi lancé par le processus de plus haut niveau qu’est le programme. SI j'ai raison; à quoi sert le fork au final ?
    Je me permet de poser la question sur le topic vu que ça doit toucher à la mémoire également.

    Ces primitives s'utilise avec #define POSIX_C_SOURCE 1 sauf erreur.

  9. #9
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Je souhaitais juste préciser une chose :
    malloc,calloc,realloc,free, sont des appels systèmes.
    Une petite précision, malloc, calloc, realloc et free ne sont pas des appels système, et heureusement sinon ça plomberait les programmes.

    Ce sont des fonctions implémentées par la bibliothèque standard C, libc ou glibc sur Unix/Linux. Des implémentations externes s'appuyant sur de l'interposition existent aussi, soit pour optimiser les performances pour des cas particuliers, soit à des fins de déboguage (ex: valgrind).

    Bien sûr, comme la plupart des autres fonctions de la bibliothèque standard, les appels à ces fonctions entraînent parfois des appels système sous jacents comme brk(2) et mmap(2) sous Unix mais, le plus souvent, le traitement est uniquement en mode utilisateur et pas système.

    Citation Envoyé par Sve@r Voir le message
    Exact. Toutefois malloc/calloc ne se justifient vraiment que si tu ne connais pas la taille à l'avance quand le tu écris le programme.
    Pas seulement. Si la zone allouée a une durée de vie courte, il est préférable d'utiliser malloc/free plutôt qu'un tableau statique dont on ne pourra pas libérer/réutiliser l'espace mémoire.

    C'est la règle de base. Mais il est important de savoir que realloc peut échouer. Et dans ce cas, tu as perdu la zone initiale.
    C'est tout a fait faux, realloc préserve heureusement la zone initiale en cas d'échec.
    ɹǝsn *sıɹɐlos*

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Amnael Voir le message
    A priori, si cela revient au même on peut s'en passer donc.
    Quand j'ai dit que ça revenait au même, je voulais dire qu'une adresse reste une adresse et donc écrire int *pt=(char*)malloc(sizeof(int)) fonctionnera même si le compilo s'arrache les yeux.
    Toutefois aujourd'hui certains (dont moi) préfèrent ne pas caster malloc. Ca permet de détecter qu'on a oublié d'inclure stdlib.h (car dans ce cas malloc est vu comme int et non comme void* et donc le compilo gueule quand on écrit int *pt=malloc(...).

    Citation Envoyé par Amnael Voir le message
    Dans mon cas je ne vais pas passer par un pointeur temporaire sur le realloc; on considère que si la ré-allocation plante le programme s'arrête.
    Pas très propre. Tu sors sans nettoyer derrière toi. Pour un TP ou un test rapide ça va mais pour un projet un tant soi peu professionnel, c'est inacceptable. Surtout que sur certains OS, la mémoire non libérée est perdue même pour l'OS. Il faut alors rebooter pour la récupérer.
    Mais même sans ça tu ne peux pas programmer d'une certaine façon dans un cas et d'une autre dans un autre. Si tu prends maintenant l'habitude de négliger certains aspects importants en te disant "c'est pas grave ce n'est qu'un TP", tu les négligeras aussi quand ça sera du sérieux.

    Citation Envoyé par Amnael Voir le message
    Je change totalement de sujet pour le coup; on a également quelques primitives systèmes en C permettant d’obtenir le pid d'un processus; ainsi que de créer des processus avec fork()

    Ma question parait bête mais lorsque l'on utile fork pour créer un processus fils d'un processus père. Que fait le processus ?

    Je pensais que l'utilisation d'une fonction dans un programme était considérer comme un processus en soi lancé par le processus de plus haut niveau qu’est le programme. SI j'ai raison; à quoi sert le fork au final ?
    Je me permet de poser la question sur le topic vu que ça doit toucher à la mémoire également.
    Ca c'est carrément un autre sujet.
    L'appel à une fonction n'est absolument pas un autre processus. C'est le processus actuel qui part dans une autre partie du code puis qui revient là où il en était. Un peu comme si tu es sur autoroute puis tu décides de sortir visiter un village puis 2h après tu reviens sur l'autoroute. Durant ta sortie tu as "mis en attente" toute ta problématique de conduite sur autoroute (gestion des camions, des dépassements, etc). Tu fais carrément autre chose (tu manges une glace, visites les boutiques) puis en revenant sur l'autoroute tu reprends ta problématique de conduite rapide.

    Le fork, lui, génère vraiment un second processus qui duplique le code là où il est appelé. A partir de là, tout le code suivant est exécuté deux fois (une fois par le processus d'origine, une seconde fois par le processus créé). C'est comme si sur autoroute tu avais maintenant deux voitures indépendantes à conduire.
    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>
    int main()
     
    {
    	fork();
    	printf("Hello (%d/%d)\n", getppid(), getpid());
    }

    Bien entendu, faire deux fois la même chose c'est un peu idiot. On préfèrera utiliser P1 pour faire une action X et P2 pour faire une action Y. On peut faire la différence avec la valeur renvoyée par fork() (dans le père elle vaut le pid du fils et dans le fils
    Et les deux actions d'effectueront "en même temps". Elles pourront même se communiquer des infos (mais faudra passer par des outils spécialisés car les processus sont totalement indépendants et ont leur propre mémoire)

    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
    #include <stdio.h>
    int main()
    {
    	int pid;
    	int i;
    	switch (pid=fork())
    	{
    		case -1: // Erreur de fork - A gérer
    			break;
    		case 0: // Fils
    			for (i=0; i < 10; i++)
    				printf("i=%d - Je suis le fils %d de %d\n", i, getpid(), getppid());
     
    			// Eventuellement exit(0) pour arrêter le processus fils
    			break;
    		default: // Pere
    			for (i=0; i < 10; i++)
    				printf("i=%d - Je suis le père %d de %d\n", i, getpid(), pid);
    	}
    	printf("Hello\n");		// Pour bien montrer que le fork ne s'arrête pas au switch et que toute le reste du code a été dupliqué - C'est pour ça que exit(0) dans le fils est souvent nécessaire...
    }

    Citation Envoyé par jlliagre Voir le message
    Citation Envoyé par Sve@r Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    t=realloc(t, 8 * sizeof(int))
    C'est la règle de base. Mais il est important de savoir que realloc peut échouer. Et dans ce cas, tu as perdu la zone initiale.
    C'est tout a fait faux, realloc préserve heureusement la zone initiale en cas d'échec.
    Je n'ai pas dit que realloc perdait la zone initiale (sinon mon second exemple ne pourrait pas fonctionner), j'ai dit "tu (au codeur) as perdu" parce que le codeur aura affecté un realloc échoué au pointeur initial. Mais effectivement j'aurais pû écrire plutôt "et avec ce type de code tu as perdu..."
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Membre expérimenté

    Homme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 545
    Points : 1 429
    Points
    1 429
    Par défaut
    Bonjour,

    Malgré tout, il me semble que beaucoup de gens néglige l'aspect architectural d'un ordinateur.
    Tu as bien raison de t'intéressé aux architectures.

    Je te conseille vivement la lecture des articles suivant concernant un point essentiel de la programmation, qui est la gestion de la mémoire par le hardware.

    http://en.wikipedia.org/wiki/Memory_management_unit (article en anglais plus complet que celui en français...)
    http://fr.wikipedia.org/wiki/M%C3%A9moire_cache

  12. #12
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Pour chaque allocation, on sauvegarde l'emplacement en mémoire de la zone alloué, la taille, et surement le système garde aussi un identifiant pour connaître le propriétaire. (Ce qui permettra, lorsqu'un autre programme essaie d'accéder à une zone mémoire qui n'est pas à lui, de lui faire une erreur de segmentation).
    Désolé mais une autre rectification:

    Il n'y a pas de notion de propriétaire pour la mémoire allouée avec malloc/calloc/realloc, il s'agit de mémoire virtuelle qui appartient au processus courant (et à ses threads le cas échéant) et n'a donc par définition qu'un unique propriétaire.

    Il existe d'autres méthodes d'allocation mémoire où une notion de propriétaire et de droits d'accès existe mais elles concernent la mémoire partagée entre processus et ne fait pas appel à malloc.

    Une erreur de segmentation survient lorsqu'une instruction tente d'accéder à une adresse mémoire qui est hors des zones autorisées au processus qui sont la pile (stack), les données (data+bss+heap) et le code (text). Cette mémoire "hors-zone" n'appartient pas à quelqu'un d'autre, elle n'existe tout simplement pas.
    ɹǝsn *sıɹɐlos*

  13. #13
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    Merci pour les corrections
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  14. #14
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    alors qu'avec calloc, la mémoire est remplie de "zéros", ce qui correspond à 0 pour les types numériques entiers ou flottants, à des pointeurs nuls pour les types pointeur, et à des chaines vides pour les chaines de caractères.
    Pour être précis, calloc() initialise à "tous les bits à 0", ce qui correspond effectivement à initialiser à 0 pour les types entiers (et à des chaînes vides puisque char est un type entier). Par contre il n'y a pas de garantie que "tous les bits à 0" correspondent à 0 sur les types réels ou au pointeur NULL.

  15. #15
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 882
    Points
    7 882
    Par défaut
    Citation Envoyé par gl Voir le message
    Par contre il n'y a pas de garantie que "tous les bits à 0" correspondent à 0 sur les types réels ou au pointeur NULL.
    C'est vrai, par de garantie car le standard ne l'exige pas.
    Cependant en pratique, il faut probablement chercher dans un musée une machine qui écrit ses pointeurs NULL avec autre chose que des zéros (bon peut-être que des mainframes font encore çà) et il doit être encore plus difficile de trouver une machine / bibliothèque mathématique qui implémente une unité de calcul en virgule flottante ne s'appuyant pas sur l'encodage IEEE 754, pour qui les trois champs à 0 représentent bien toujours +0.0.
    ɹǝsn *sıɹɐlos*

  16. #16
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    Cependant en pratique, il faut probablement chercher dans un musée une machine qui écrit ses pointeurs NULL avec autre chose que des zéros (bon peut-être que des mainframes font encore çà) et il doit être encore plus difficile de trouver une machine / bibliothèque mathématique qui implémente une unité de calcul en virgule flottante ne s'appuyant pas sur l'encodage IEEE 754, pour qui les trois champs à 0 représentent bien toujours +0.0.
    Pour les pointeurs ! Pas nécessairement, il suffit d'aller du côté de l'embarqué sans MMU avec un adressage linéaire où l'adresse 0 est une adresse utilisable et où le pointeur NULL est plutôt "tous les bits à 1" qui donne une adresse inexistante (voir qui trap).

    Pour les réels, j'ai vu des plateformes ne les supportant pas du tout(du coup pour le respect du standard on repassera) ou sous option, mais effectivement lorsqu'ils sont supportés j'ai toujours vu de l'IEEE 754. Mais j'ai tendance à me méfie de la généralisation de ma propre expérience.

  17. #17
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Hello;

    afin de continuer à bidouiller un peu sur les allocations je me suis amusé à essayé de "reproduire" le code de la fonction strcat qui concatène deux chaines de caractère

    Je ne crois pas avoir fait d'erreur mais je ne retiens que la première chaine; je vous laisse voir par vous même.

    concat("Bonjour","mon ami");
    ne m'affiche que Bonjour en chaine 3

    Au début j'ai pensé que c'était peut être l'affichage d'un %s qui s'arrêtait dès que l'on rencontrait un \0; mais même après modification ça ne change rien. Une idée ?

    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
    char* concat(char* ch1,char* ch2)
    {
    	int size1=strlen(ch1);
    	int size2=strlen(ch2);
    	printf("La chaine 1 vaut %s\n",ch1);
    	printf("La chaine 2 vaut %s\n",ch2);
    	char *ch3=NULL;
    	ch3=calloc((size1+size2),sizeof(char));
    		if(ch3==NULL)
    		{
    			fprintf(stderr, "Erreur calloc: échec de l'allocation mémoire de la chaine\n");
        	exit(1); //on quitte si le calloc plante
    		}
    	int k;
    	for (k=0;k<size1;k++)
    	{
    		ch3[k]=ch1[k];
    		if (ch3[k]=='\0')
    		{
    			ch3[k]=' ';
    		}
    	}
    	int cpt=0;
    	for (k=size1;k<size2;k++)
    	{
    		ch3[k]=ch2[cpt];
    		cpt++;
    	}
    	printf("La chaine 3 vaut %s\n",ch3);
    	return ch3;
    }

  18. #18
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    Regardez :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (k=size1;k<size2;k++)
    D'après vous, quelles sont les valeurs de size1 et size2 ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  19. #19
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Je suis une courge ---'


    Merci x)

  20. #20
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    1- La quantité allouée est insuffisante : eslle doit être de size1+size2+1 (+1 pour le zéro terminal de la chaine finale)

    2-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    		if (ch3[k]=='\0')
    		{
    			ch3[k]=' ';
    		}
    A quoi sert ce code ?

    3-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	for (k=size1;k<size2;k++)
    	{
    		ch3[k]=ch2[cpt];
    		cpt++;
    	}
    La boucle est fausse : c'est cpt qui est limité par size2, pas k

    4- par exemple (voir commentaires)
    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
    char* concat(char* ch1,char* ch2)
    {
       int size1=strlen(ch1);
       int size2=strlen(ch2);
       char *ch3;
       int k, cpt;
       ch3=malloc(size1+size2+1);  // cf (1) et pourquoi calloc() ?  
       if(ch3==NULL)
       {
          fprintf(stderr, "Erreur calloc: échec de l'allocation mémoire de la chaine\n");
          exit(1); //on quitte si le calloc plante
       }
       for (k=0;k<size1;k++)ch3[k]=ch1[k];   // cf(2)
       for (cpt=0;cpt<size2;cpt++)           // cf(3)
       {
          ch3[k]=ch2[cpt];
          k++;
       }
       ch3[k] = '\0' ;                    // le zéro terminal
       printf("La chaine 3 vaut %s\n",ch3);
       return ch3;
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

Discussions similaires

  1. Comment fonctionnent les "keywords"
    Par shikakus dans le forum Référencement
    Réponses: 3
    Dernier message: 29/01/2007, 00h13
  2. Comment fonctionne les versions d'un logiciel?
    Par Antigonos Ier Gonatas dans le forum Windows
    Réponses: 12
    Dernier message: 14/07/2006, 18h48
  3. [VB6] Comment fonctionne les Tableaux ?
    Par Lucas42 dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 27/04/2006, 14h59
  4. [FLASH 8] Comment fonctionne les clips
    Par steeves5 dans le forum Flash
    Réponses: 3
    Dernier message: 27/01/2006, 10h23
  5. Comment fonctionnent les index des options d'un select ?
    Par pekka77 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 31/10/2005, 18h05

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