Allocation mémoire petit programme C
Fermé
sabrina
-
31 janv. 2013 à 14:33
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 4 févr. 2013 à 21:45
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 4 févr. 2013 à 21:45
A voir également:
- Allocation mémoire petit programme C
- Programme demarrage windows 10 - Guide
- Mémoire vive - Guide
- Mémoire vidéo dédiée : 128 mo ✓ - Forum Carte graphique
- Programme (x86) ✓ - Forum Windows
13 réponses
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
Modifié par nicocorico le 31/01/2013 à 20:57
Modifié par nicocorico le 31/01/2013 à 20:57
1- Une zone de mémoire est allouée pour ce qui constitue le corps du programme ainsi que les constantes, donc la zone fait la dimension adéquate tout bonnement. Ensuite le programme peut avoir des dépendances, dll ou autres paquets qui seront eux aussi alloués dans leur bloc de mémoire propre.
2- Non non, la mémoire physique n'est pas découpée en pages, cependant le programme lui-même intègre un gestionnaire de mémoire qui lui utilise des pages, c'est ce qu'on appelle la mémoire locale...Ce gestionnaire alloue sa mémoire dans le tas, évidemment puisque c'est la seule mémoire réellement existante à l'origine, celle-ci étant gérée par l'OS.
3- Les variables locales sont mises sur la pile oui, mais pas les fonctions. La pile est une mémoire très temporaire, elle ne convient en rien à l'exécution d'une routine. De plus cette hypothétique routine il faudrait bien la charger à chaque fois, donc l'avoir quelque part en mémoire, ailleurs! Donc ça répond en gros à l'ensemble de la question, en précisant que la pile fonctionne à l'envers, donc les adresses plus hautes sont plus anciennes... Et en fait tout se trouve en mémoire à des endroits différents, y compris la pile, donc le fait que des adresses soient proches ne signifie pas qu'elles font partie d'un même bloc ou même qu'elles aient quoique ce soit en commun.
4-TOUT est sur le tas...si tu as 2 go de mémoire dans l'ordi les adresses valides s'étalent de 0 à 2147483648... Tout sera alloué dans cet espace, les routines des programmes, leurs constantes et leurs piles (au moins une par programme).
à savoir que la pile elle-même peut être déplacée à la volée, pour l'agrandir par-exemple. Son adresse n'est donc pas figée en exécution.
Le chêne aussi était un gland, avant d'être un chêne
2- Non non, la mémoire physique n'est pas découpée en pages, cependant le programme lui-même intègre un gestionnaire de mémoire qui lui utilise des pages, c'est ce qu'on appelle la mémoire locale...Ce gestionnaire alloue sa mémoire dans le tas, évidemment puisque c'est la seule mémoire réellement existante à l'origine, celle-ci étant gérée par l'OS.
3- Les variables locales sont mises sur la pile oui, mais pas les fonctions. La pile est une mémoire très temporaire, elle ne convient en rien à l'exécution d'une routine. De plus cette hypothétique routine il faudrait bien la charger à chaque fois, donc l'avoir quelque part en mémoire, ailleurs! Donc ça répond en gros à l'ensemble de la question, en précisant que la pile fonctionne à l'envers, donc les adresses plus hautes sont plus anciennes... Et en fait tout se trouve en mémoire à des endroits différents, y compris la pile, donc le fait que des adresses soient proches ne signifie pas qu'elles font partie d'un même bloc ou même qu'elles aient quoique ce soit en commun.
4-TOUT est sur le tas...si tu as 2 go de mémoire dans l'ordi les adresses valides s'étalent de 0 à 2147483648... Tout sera alloué dans cet espace, les routines des programmes, leurs constantes et leurs piles (au moins une par programme).
à savoir que la pile elle-même peut être déplacée à la volée, pour l'agrandir par-exemple. Son adresse n'est donc pas figée en exécution.
Le chêne aussi était un gland, avant d'être un chêne
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
Modifié par nicocorico le 31/01/2013 à 22:26
Modifié par nicocorico le 31/01/2013 à 22:26
-Hé bien, la mémoire physique est bien découpée oui, mais en blocs de taille variable, c'est ce qui explique que l'on peut allouer un bloc continu d'un gigaoctets par exemple tant que la taille disponible le permet!
Mais ce que tu dis est vrai pour la pagination, encore faut-il l'employer... Et ça, ça reste du bon vouloir de chaque programme et de son gestionnaire de mémoire propre, c'est à dire celui que le compilateur intègre dans l'exécutable.
Et elle est un peu employée sous windows, pour charger les dll je crois, mais là aussi c'est totalement dépendant de l'OS.
-Oui mais en fait les adresses que tu relevais sont celles des fonctions elles-mêmes, ça n'a rien à voir avec leur appel via la pile si tu veux! De plus, précisément ce n'est pas "l'appel" de fonction qui se trouve sur la pile, mais l'adresse d'où est effectué cet appel, ça permettra de revenir au point de départ lorsque la fonction rendra la main. C'est donc simplement l'adresse de retour...
-Et le tas ne commence pas à l'adresse 0 non, mais la mémoire physique oui!
En pratique l'OS occupe une partie de la mémoire au début de celle-ci bien sûr, donc le tas commence après une certaine zone réservée.
Le chêne aussi était un gland, avant d'être un chêne
Mais ce que tu dis est vrai pour la pagination, encore faut-il l'employer... Et ça, ça reste du bon vouloir de chaque programme et de son gestionnaire de mémoire propre, c'est à dire celui que le compilateur intègre dans l'exécutable.
Et elle est un peu employée sous windows, pour charger les dll je crois, mais là aussi c'est totalement dépendant de l'OS.
-Oui mais en fait les adresses que tu relevais sont celles des fonctions elles-mêmes, ça n'a rien à voir avec leur appel via la pile si tu veux! De plus, précisément ce n'est pas "l'appel" de fonction qui se trouve sur la pile, mais l'adresse d'où est effectué cet appel, ça permettra de revenir au point de départ lorsque la fonction rendra la main. C'est donc simplement l'adresse de retour...
-Et le tas ne commence pas à l'adresse 0 non, mais la mémoire physique oui!
En pratique l'OS occupe une partie de la mémoire au début de celle-ci bien sûr, donc le tas commence après une certaine zone réservée.
Le chêne aussi était un gland, avant d'être un chêne
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
31 janv. 2013 à 16:21
31 janv. 2013 à 16:21
Salut.
1- C'est l'OS, la taille est moins celle du programme, mais ça peut être plus selon sa politique de gestion.
Pour le reste, ouvre ton programme avec un éditeur hexadécimal, tu devrais mieux comprendre ce qui se passe.
Ce qui me perturbe c'est que tu n'as pas les même longueurs de nombre en sortie.
1- C'est l'OS, la taille est moins celle du programme, mais ça peut être plus selon sa politique de gestion.
Pour le reste, ouvre ton programme avec un éditeur hexadécimal, tu devrais mieux comprendre ce qui se passe.
Ce qui me perturbe c'est que tu n'as pas les même longueurs de nombre en sortie.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Delared
Messages postés
8
Date d'inscription
jeudi 31 janvier 2013
Statut
Membre
Dernière intervention
20 mars 2013
31 janv. 2013 à 20:26
31 janv. 2013 à 20:26
Bonjour, moi aussi je rejoins "Char Snipeur", tout dépend de la politique de gestion de votre système d'exploitation, mais ce qui m'inquiète aussi c'est le fait d'avoir des longueurs différentes!!!
Par exemple sous Windows 7, j'ai compilé le même programme et ça donne des Adresses de même longueur!:
A+
Par exemple sous Windows 7, j'ai compilé le même programme et ça donne des Adresses de même longueur!:
@main: 0x00401290 @printf: 0x00401880 @c: 0x0022FF44 @a: 0x0022FF43 @*str: 0x00403000
A+
Bonjour nico, alors je te réponds:
1. OK
2. Dans un tuto, il est clairement dit que pour la pagination, on découpe la mémoire physique en blocs et que la zone mémoire de chaque processus (adresses logiques) est divisée en pages de même taille que les blocs...donc la mémoire physique est bien découpée non?
3. dans tous les cours que j'ai pu trouver sur le net, il est clairement dit que les appels de fonctions sont sur la pile contrairement à ce que tu dis ....?
4. OK mais le tas je me demande vraiment si il commence à l'adresse 0 je suis pas sûre, comment le vérifier?
1. OK
2. Dans un tuto, il est clairement dit que pour la pagination, on découpe la mémoire physique en blocs et que la zone mémoire de chaque processus (adresses logiques) est divisée en pages de même taille que les blocs...donc la mémoire physique est bien découpée non?
3. dans tous les cours que j'ai pu trouver sur le net, il est clairement dit que les appels de fonctions sont sur la pile contrairement à ce que tu dis ....?
4. OK mais le tas je me demande vraiment si il commence à l'adresse 0 je suis pas sûre, comment le vérifier?
OK, j'ai juste une dernière remarque, tu dis que les adresses les plus hautes sont les plus anciennes, il me semble que c'est l'inverse, si je prends 2 variables, je mets une première variable sur la pile, si j'en ajoute une seconde, je pousse la première VERS LE BAS et la seconde a donc une adresse plus haute et est donc plus récente, non?
Donc si je récapitule: un programme a grossomodo 2 segments de mémoire, la pile qui contient les variables locales et appels de fonctions et le tas qui contient tout le reste, et ce tas est découpé en pages de 4ko qui ont une correspondance avec des adresses physiques via une table du mmu?
PS: comment savoir exactement où commence le tas dans mon programme? Je connais son adresse de fin (le fameux break) mais pas son adresse de début...
Donc si je récapitule: un programme a grossomodo 2 segments de mémoire, la pile qui contient les variables locales et appels de fonctions et le tas qui contient tout le reste, et ce tas est découpé en pages de 4ko qui ont une correspondance avec des adresses physiques via une table du mmu?
PS: comment savoir exactement où commence le tas dans mon programme? Je connais son adresse de fin (le fameux break) mais pas son adresse de début...
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
1 févr. 2013 à 07:02
1 févr. 2013 à 07:02
Hé bien justement non puisque la pile fonctionne à l'envers, avant d'y placer une valeur il faut décrémenter, et incrémenter pour libérer celle-ci. Il y a une raison logique à ça (évidemment) c'est du fait qu'on puisse y placer des valeurs de différentes tailles -de 1, 2 ou 4 octets en pratique- avec le fonctionnement inversé, lorsqu'on place une nouvelle valeur on peut toujours accéder à celle-ci sans prendre en compte le déplacement occasionné... Plus clairement, en fonctionnement "positif" on incrémente puis on écrit à la position précédente de la pile, alors que dans le système employé, on décrémente et on écrit à la position en cours de la pile...C'est plus simple à utiliser et ça économise de la mémoire au sein du programme sans aucune contrepartie (à part devoir expliquer pourquoi!).
Ensuite, le mmu est à peu près inaccessible aux programmes et son fonctionnement est transparent la plupart du temps. C'est une pagination strictement matérielle sur laquelle il n'y a ni contrôle ni retour d'information...Pour ce qui reste d'accessible au programmeur plus que de pagination, on parlerait de granularité: puisque des zones doivent être définies avec des contrôles d'accès différents, il est nécessaire d'entretenir un enregistrement concernant chacune d'elles, et pour que le mmu sache très rapidement si le type d'accès est autorisé pour la zone il est nécessaire d'avoir un zonage...Ainsi il trouve de suite l'enregistrement correspondant à une zone grâce à une simple division de l'adresse. Et en fait, les segments sont désuets car justement ils correspondaient à une adresse physique, on utilise désormais des sélecteurs, qui sont des enregistrements décrivant un segment et ses privilèges...
Et l'action du mmu concerne bien l'ensemble de la mémoire, pas seulement une zone précise!
Et en fait pour préciser le découpage mémoire d'un programme, il y a seulement deux type d'accès privilégiés, celui du code et celui des variables. D'autre part des variables peuvent être présentes dans le code. Donc on a deux sélecteurs au minimum, avec des privilèges d'accès différents, et en pratique tout est alloué sur le tas...C'est à dire que l'OS alloue un bloc pour y copier l'actif du programme lui-même et ensuite c'est selon le programme, mais la plupart intègrent un gestionnaire de mémoire qui alloue des blocs sur le tas pour ensuite les découper, c'est ce qu'on appelle l'allocation mémoire locale...Il faut donc bien comprendre que tout provient du tas, ensuite c'est de la sous-allocation...
Quant à savoir l'adresse réelle, je sais pas si c'est possible! Et, à quoi bon?
Ensuite, le mmu est à peu près inaccessible aux programmes et son fonctionnement est transparent la plupart du temps. C'est une pagination strictement matérielle sur laquelle il n'y a ni contrôle ni retour d'information...Pour ce qui reste d'accessible au programmeur plus que de pagination, on parlerait de granularité: puisque des zones doivent être définies avec des contrôles d'accès différents, il est nécessaire d'entretenir un enregistrement concernant chacune d'elles, et pour que le mmu sache très rapidement si le type d'accès est autorisé pour la zone il est nécessaire d'avoir un zonage...Ainsi il trouve de suite l'enregistrement correspondant à une zone grâce à une simple division de l'adresse. Et en fait, les segments sont désuets car justement ils correspondaient à une adresse physique, on utilise désormais des sélecteurs, qui sont des enregistrements décrivant un segment et ses privilèges...
Et l'action du mmu concerne bien l'ensemble de la mémoire, pas seulement une zone précise!
Et en fait pour préciser le découpage mémoire d'un programme, il y a seulement deux type d'accès privilégiés, celui du code et celui des variables. D'autre part des variables peuvent être présentes dans le code. Donc on a deux sélecteurs au minimum, avec des privilèges d'accès différents, et en pratique tout est alloué sur le tas...C'est à dire que l'OS alloue un bloc pour y copier l'actif du programme lui-même et ensuite c'est selon le programme, mais la plupart intègrent un gestionnaire de mémoire qui alloue des blocs sur le tas pour ensuite les découper, c'est ce qu'on appelle l'allocation mémoire locale...Il faut donc bien comprendre que tout provient du tas, ensuite c'est de la sous-allocation...
Quant à savoir l'adresse réelle, je sais pas si c'est possible! Et, à quoi bon?
totof31
Messages postés
163
Date d'inscription
lundi 29 octobre 2012
Statut
Membre
Dernière intervention
30 avril 2013
74
1 févr. 2013 à 11:57
1 févr. 2013 à 11:57
3. dans tous les cours que j'ai pu trouver sur le net, il est clairement dit que les appels de fonctions sont sur la pile contrairement à ce que tu dis ....?
Pour que ce soit plus clair : il s'agit uniquement des paramètres passés à la fonction, pas du code des fonctions elles-mêmes, qui ont leur propre section mémoire.
D'ailleurs, il ne faut pas généraliser : avec l'architecture ARM par exemple (voir document AAPCS), les compilos passent jusqu'aux 4 premiers paramètres dans des registres, puis s'il y a d'autres paramètres, ils les mettent sur la pile. Et je ne parle pas de compilation en mode optimisé, où le compilo va essayer de se passer de la pile le plus possible...
Pour que ce soit plus clair : il s'agit uniquement des paramètres passés à la fonction, pas du code des fonctions elles-mêmes, qui ont leur propre section mémoire.
D'ailleurs, il ne faut pas généraliser : avec l'architecture ARM par exemple (voir document AAPCS), les compilos passent jusqu'aux 4 premiers paramètres dans des registres, puis s'il y a d'autres paramètres, ils les mettent sur la pile. Et je ne parle pas de compilation en mode optimisé, où le compilo va essayer de se passer de la pile le plus possible...
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
1 févr. 2013 à 18:00
1 févr. 2013 à 18:00
Oui bon, le sujet initial portait bien sur l'adresse de la fonction elle-même, mais ceci dit le fait de pouvoir passer les paramètres par la pile fait partie de la confusion.
Et effectivement les registres sont largement utilisés à cette fin plutôt que la pile, mais ça dépend du compilateur et de la convention d'appel employée, le passage des paramètres par les registres restant limité aux routines locales apparemment. J'ignore commet ça se passe sous d'autres OS mais toutes les fonctions windows exigent les paramètres sur la pile.
Et effectivement les registres sont largement utilisés à cette fin plutôt que la pile, mais ça dépend du compilateur et de la convention d'appel employée, le passage des paramètres par les registres restant limité aux routines locales apparemment. J'ignore commet ça se passe sous d'autres OS mais toutes les fonctions windows exigent les paramètres sur la pile.
bonjour nico, en fait tout n'est pas encore clair, tu es bien d'accord que l'os alloue de la mémoire à mon programme, alors moi je souhaite savoir ceci:
1. comment savoir quelle taille mémoire l'os alloue à mon programme, il n'y a pas une fonction C qui fait ceci?
2. Dans la mémoire de mon programme il y a si je pars du bas, le segment text, le segment data, le segment bss, le heap et la pile d'accord? Es tu d'accord que les segments data,bss et text ne font pas partie du tas, ce sont des parties bien distinctes, je veux dire quand on fait un malloc il n'y a que le heap de concerné tu es d'accord?
3. La mémoire physique commence à 0 et notre programme ne voit que des adresses virtuelles, j'aimerais bien connaitre les adresses de ces 5 sections de mon petit programme, est ce possible?
merci
1. comment savoir quelle taille mémoire l'os alloue à mon programme, il n'y a pas une fonction C qui fait ceci?
2. Dans la mémoire de mon programme il y a si je pars du bas, le segment text, le segment data, le segment bss, le heap et la pile d'accord? Es tu d'accord que les segments data,bss et text ne font pas partie du tas, ce sont des parties bien distinctes, je veux dire quand on fait un malloc il n'y a que le heap de concerné tu es d'accord?
3. La mémoire physique commence à 0 et notre programme ne voit que des adresses virtuelles, j'aimerais bien connaitre les adresses de ces 5 sections de mon petit programme, est ce possible?
merci
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
3 févr. 2013 à 22:24
3 févr. 2013 à 22:24
Bonjour,
Oui normalement il doit y avoir une fonction pour connaitre la taille de l'espace mémoire utilisé par le programme, il faut pour cela se pencher sur les fonctions du gestionnaire de mémoire (je connais pas le C)...
Heuu? Les segments text, bss, data? Qu'est-ce? Le processeur distingue les segments utilisé pour l'accès au programme, aux données et à la pile oui; Ce sont les registres Cs pour le programme, SS pour la pile et 4 registres de segment pour les données (Ds, Es, Fs et Gs), mais généralement ces 5 segments de données ont le même contenu. Par ailleurs le segment de code permet normalement l'accès en lecture et en écriture afin d'y loger des variables. En fait je crois comprendre que le C distingue différents espaces pour les chaines, les variables et la pile...Mais toutes ces zones sont logiquement allouées dans le tas global...C'est à dire que l'Os charge le programme et les dll associées d'une manière éventuellement particulière -et encore-, mais tout ce que le programme alloue par la suite provient bel et bien du tas...En fait je dirais même que toute mémoire employée sous l'OS est préalablement allouée dans le tas, du moins je ne sais pas dans quelle mesure une partie de la mémoire serait réservée en dehors de ce tas -à part pour le Kernel-, qui est la mémoire à disposition pour toute utilisation...Ensuite il y a différents gestionnaires de mémoire oui, mais tous piochent leurs ressources dans le tas global si je ne m'abuse!
Quant à récupérer les adresses physiques, hé bien c'est pas gagné! En fait ça n'a pas vraiment d'intérêt à l'usage donc je crois que c'est impossible...En assembleur tu peux récupérer le descripteur de segment de la GDT avec l'instruction LLDT ou bien directement les limites de segment avec l'instruction LSL, mais là encore ça te permettra seulement d'avoir l'adresse logique, je ne crois pas qu'il soit possible d'accéder aux pages d'allocation du mmu, malheureusement!
Oui normalement il doit y avoir une fonction pour connaitre la taille de l'espace mémoire utilisé par le programme, il faut pour cela se pencher sur les fonctions du gestionnaire de mémoire (je connais pas le C)...
Heuu? Les segments text, bss, data? Qu'est-ce? Le processeur distingue les segments utilisé pour l'accès au programme, aux données et à la pile oui; Ce sont les registres Cs pour le programme, SS pour la pile et 4 registres de segment pour les données (Ds, Es, Fs et Gs), mais généralement ces 5 segments de données ont le même contenu. Par ailleurs le segment de code permet normalement l'accès en lecture et en écriture afin d'y loger des variables. En fait je crois comprendre que le C distingue différents espaces pour les chaines, les variables et la pile...Mais toutes ces zones sont logiquement allouées dans le tas global...C'est à dire que l'Os charge le programme et les dll associées d'une manière éventuellement particulière -et encore-, mais tout ce que le programme alloue par la suite provient bel et bien du tas...En fait je dirais même que toute mémoire employée sous l'OS est préalablement allouée dans le tas, du moins je ne sais pas dans quelle mesure une partie de la mémoire serait réservée en dehors de ce tas -à part pour le Kernel-, qui est la mémoire à disposition pour toute utilisation...Ensuite il y a différents gestionnaires de mémoire oui, mais tous piochent leurs ressources dans le tas global si je ne m'abuse!
Quant à récupérer les adresses physiques, hé bien c'est pas gagné! En fait ça n'a pas vraiment d'intérêt à l'usage donc je crois que c'est impossible...En assembleur tu peux récupérer le descripteur de segment de la GDT avec l'instruction LLDT ou bien directement les limites de segment avec l'instruction LSL, mais là encore ça te permettra seulement d'avoir l'adresse logique, je ne crois pas qu'il soit possible d'accéder aux pages d'allocation du mmu, malheureusement!
nicocorico
Messages postés
799
Date d'inscription
dimanche 19 juin 2011
Statut
Membre
Dernière intervention
3 juillet 2018
138
Modifié par nicocorico le 4/02/2013 à 21:46
Modifié par nicocorico le 4/02/2013 à 21:46
En fait je n'y avais pas pensé mais si tu veux une approximation globale de la taille occupée par ton programme, il suffit de le lancer et de regarder dans le gestionnaire de tâche, à l'onglet processus...ainsi tu peux même suspendre l'exécution de ton programme à un moment donné (en pas-à-pas) et donc savoir ce qu'il consomme à n'importe quel moment de son exécution, en toute simplicité!
Du côté de la récupération de l'adresse physique, quelques espoirs après avoir creusé un peu!
Notamment ici http://3kernels.free.fr/divers/support/ipi/msdos/modes-d-adressages_pc-mmu-x86.pdf il y a des éléments intéressants.
En fait la table de pagination se trouve à une adresse définie comme étant le PTBR et semble correspondre au registre spécial CR3 sur x86, facilement accessible avec l'instruction spéciale "Mov CR3,EAX" qui permettrait donc de récupérer l'adresse PTBR dans EAX donc...Cette table contient les numéros de blocs réels et permet donc de savoir où ils sont physiquement localisés.
Du côté de la récupération de l'adresse physique, quelques espoirs après avoir creusé un peu!
Notamment ici http://3kernels.free.fr/divers/support/ipi/msdos/modes-d-adressages_pc-mmu-x86.pdf il y a des éléments intéressants.
En fait la table de pagination se trouve à une adresse définie comme étant le PTBR et semble correspondre au registre spécial CR3 sur x86, facilement accessible avec l'instruction spéciale "Mov CR3,EAX" qui permettrait donc de récupérer l'adresse PTBR dans EAX donc...Cette table contient les numéros de blocs réels et permet donc de savoir où ils sont physiquement localisés.