Dans quel segment (.BSS, .DATA, autre) d'un fichier exécutable sont des variables statiques stockées afin qu'elles n'aient pas de collision de noms? Par exemple:
foo.c: bar.c:
static int foo = 1; static int foo = 10;
void fooTest() { void barTest() {
static int bar = 2; static int bar = 20;
foo++; foo++;
bar++; bar++;
printf("%d,%d", foo, bar); printf("%d, %d", foo, bar);
} }
Si je compile les deux fichiers et le lie à un main qui appelle fooTest () et barTest à plusieurs reprises, les instructions printf s'incrémentent indépendamment. Cela a du sens puisque les variables foo et bar sont locales à l'unité de traduction.
Mais où est alloué le stockage?
Pour être clair, l'hypothèse est que vous disposez d'une chaîne d'outils qui produirait un fichier au format ELF. Ainsi, je crois qu'il doit y avoir un espace réservé dans le fichier exécutable pour ces variables statiques.
À des fins de discussion, supposons que nous utilisons la chaîne d'outils GCC.
c++
c
compiler-construction
Benoit
la source
la source
Réponses:
La destination de vos statiques dépend du fait qu'elles sont initialisées à zéro . les données statiques initialisées à zéro vont dans .BSS (Block Started by Symbol) , les données non initialisées à zéro entre dans .DATA
la source
.data
et des données statiques sans initialiseur sont entrées.bss
.Lorsqu'un programme est chargé en mémoire, il est organisé en différents segments. L'un des segments est le segment DATA . Le segment de données est en outre sous-divisé en deux parties:
Segment de données initialisé: toutes les données globales, statiques et constantes sont stockées ici.
Segment de données non initialisé (BSS): toutes les données non initialisées sont stockées dans ce segment.
Voici un diagramme pour expliquer ce concept:
voici un très bon lien expliquant ces concepts:
la source
En fait, une variable est un tuple (stockage, portée, type, adresse, valeur):
La portée locale peut signifier local pour l'unité de traduction (fichier source), la fonction ou le bloc selon l'endroit où il est défini. Pour rendre la variable visible à plus d'une fonction, elle doit certainement être dans la zone DATA ou BSS (selon qu'elle est initialisée explicitement ou non, respectivement). Il est ensuite étendu en conséquence à toutes les fonctions ou à toutes les fonctions du fichier source.
la source
L'emplacement de stockage des données dépendra de la mise en œuvre.
Cependant, le sens de statique est «lien interne». Ainsi, le symbole est interne à l'unité de compilation (foo.c, bar.c) et ne peut pas être référencé en dehors de cette unité de compilation. Donc, il ne peut y avoir aucune collision de noms.
la source
dans la zone "globale et statique" :)
Il existe plusieurs zones de mémoire en C ++:
Voir ici pour une réponse détaillée à votre question:
la source
Je ne crois pas qu'il y aura une collision. L'utilisation de statique au niveau du fichier (fonctions externes) marque la variable comme locale à l'unité de compilation actuelle (fichier). Il n'est jamais visible en dehors du fichier actuel et n'a donc jamais à avoir un nom pouvant être utilisé en externe.
L'utilisation de statique à l' intérieur d' une fonction est différente - la variable n'est visible que par la fonction (qu'elle soit statique ou non), c'est juste sa valeur est préservée à travers les appels à cette fonction.
En effet, la statique fait deux choses différentes selon l'endroit où elle se trouve. Dans les deux cas cependant, la visibilité de la variable est limitée de telle manière que vous pouvez facilement éviter les conflits d'espace de noms lors de la liaison.
Cela dit, je pense qu'il serait stocké dans la
DATA
section, qui a tendance à avoir des variables initialisées à des valeurs autres que zéro. Il s'agit, bien sûr, d'un détail de mise en œuvre, pas de quelque chose exigé par la norme - il ne se soucie que du comportement, pas de la façon dont les choses sont faites sous les couvertures.la source
So, how does a segment of memory (Data Segment) store variables that can be accessed from everywhere (global variables) and also those which have limited scope (file scope or function scope in case of static variables)?
Comment le trouver vous-même avec
objdump -Sr
Pour comprendre réellement ce qui se passe, vous devez comprendre la relocalisation de l'éditeur de liens. Si vous n'avez jamais touché à cela, pensez à lire d'abord cet article .
Analysons un exemple ELF Linux x86-64 pour le voir nous-mêmes:
Compiler avec:
Décompilez le code avec:
-S
décompile le code avec la source originale entremêlée-r
affiche les informations de déménagementÀ l'intérieur de la décompilation de
f
nous voyons:et le
.data-0x4
dit qu'il ira au premier octet du.data
segment.Le
-0x4
est là parce que nous utilisons l'adressage relatif RIP, donc le%rip
dans l'instruction etR_X86_64_PC32
.Il est nécessaire car RIP pointe vers l' instruction suivante , qui commence 4 octets après
00 00 00 00
quoi est ce qui sera déplacé. J'ai expliqué cela plus en détail sur: https://stackoverflow.com/a/30515926/895245Ensuite, si nous modifions la source
i = 1
et faisons la même analyse, nous concluons que:static int i = 0
continue.bss
static int i = 1
continue.data
la source
Voici comment (facile à comprendre):
la source
Cela dépend de la plate-forme et du compilateur que vous utilisez. Certains compilateurs stockent directement dans le segment de code. Les variables statiques ne sont toujours accessibles qu'à l'unité de traduction actuelle et les noms ne sont pas exportés, ce qui explique pourquoi les collisions de noms ne se produisent jamais.
la source
Les données déclarées dans une unité de compilation iront dans le .BSS ou le .Data de la sortie de ces fichiers. Données initialisées dans BSS, non activées dans DATA.
La différence entre les données statiques et globales réside dans l'inclusion des informations de symbole dans le fichier. Les compilateurs ont tendance à inclure les informations de symbole mais ne marquent que les informations globales en tant que telles.
L'éditeur de liens respecte ces informations. Les informations de symbole pour les variables statiques sont soit ignorées, soit mutilées afin que les variables statiques puissent toujours être référencées d'une manière ou d'une autre (avec des options de débogage ou de symbole). Dans les deux cas, les unités de compilation ne peuvent être affectées lorsque l'éditeur de liens résout d'abord les références locales.
la source
Je l'ai essayé avec objdump et gdb, voici le résultat que j'obtiens:
voici le résultat objdump
Donc, c'est-à-dire, vos quatre variables sont situées dans la section de données événement du même nom, mais avec un décalage différent.
la source
variable statique stockée dans un segment de données ou un segment de code comme mentionné précédemment.
Vous pouvez être sûr qu'il ne sera pas alloué sur la pile ou le tas.
Il n'y a pas de risque de collision puisque le
static
mot-clé définit la portée de la variable comme un fichier ou une fonction, en cas de collision il y a un compilateur / éditeur de liens pour vous avertir.Un bel exemple
la source
Eh bien cette question est un peu trop ancienne, mais puisque personne ne signale aucune information utile: Vérifiez le message de 'mohit12379' expliquant le magasin de variables statiques du même nom dans la table des symboles: http://www.geekinterview.com/question_details/ 24745
la source
La réponse pourrait très bien dépendre du compilateur, donc vous voudrez probablement éditer votre question (je veux dire, même la notion de segments n'est pas mandatée par ISO C ni ISO C ++). Par exemple, sous Windows, un exécutable ne porte pas de noms de symboles. Un «foo» serait le décalage 0x100, l'autre peut-être 0x2B0, et le code des deux unités de traduction est compilé en connaissant les décalages pour «leur» toto.
la source
ils seront tous les deux stockés indépendamment, mais si vous voulez le faire comprendre aux autres développeurs, vous voudrez peut-être les envelopper dans des espaces de noms.
la source
vous savez déjà qu'il stocke dans bss (début de bloc par symbole) également appelé segment de données non initialisé ou dans segment de données initialisé.
prenons un exemple simple
la variable statique ci-dessus n'est pas initialisée, elle va donc au segment de données non initialisé (bss).
et bien sûr, il a été initialisé par 10 pour qu'il passe au segment de données initialisé.
la source