Pourquoi l' .segment bss nécessaire?
Ce que je sais, c'est que globales et les variables statiques sont stockées dans le .data
segment, et des données non initialisées sont dans le .bss
segment. Ce que je ne comprends pas, c'est pourquoi nous avons segment dédié pour les variables non initialisées? Si une variable non initialisée a une valeur attribuée au moment de l'exécution, la variable existe pas encore dans le .bss
segment seulement?
Dans le programme suivant, a
est dans le .data
segment, et b
est dans le .bss
segment; est-ce exact? Veuillez me corriger si ma compréhension est erronée.
#include <stdio.h>
#include <stdlib.h>
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[20]; /* Uninitialized, so in the .bss and will not occupy space for 20 * sizeof (int) */
int main ()
{
;
}
Aussi, envisager la suite du programme,
#include <stdio.h>
#include <stdlib.h>
int var[10]; /* Uninitialized so in .bss */
int main ()
{
var[0] = 20 /* **Initialized, where this 'var' will be ?** */
}
- Vous pouvez lire BSS que Mieux Économiser de l'Espace.
Vous devez vous connecter pour publier un commentaire.
La raison est de réduire la taille du programme. Imaginez que votre C programme s'exécute sur un système embarqué, où le code et toutes les constantes sont enregistrées dans la vrai ROM (mémoire flash). Dans ces systèmes, l'initiale de "copier-bas" doivent être exécutées de manière à définir ensemble statique de la durée de stockage des objets, avant main() est appelée. Il sera généralement aller comme ce pseudo:
Où .les données et les .bss sont stockées dans la RAM, mais init_value est stocké dans la ROM. Si il avait été l'un segment, puis la ROM devait être rempli avec beaucoup de zéros, en augmentant la taille de la mémoire ROM de manière significative.
En fonction de RAM exécutables fonctionnent de la même façon, même si bien sûr ils n'ont pas de vrai ROM.
Aussi, memset est probable que certains très efficace assembleur en ligne, ce qui signifie que le démarrage de la copie peut être exécuté plus rapidement.
La
.bss
segment est une optimisation. L'ensemble de la.bss
segment est décrit par un seul nombre, probablement 4 octets 8 octets, ce qui donne à sa taille dans le processus en cours d'exécution, alors que le.data
section est aussi grand que la somme des tailles des initialisé les variables. Ainsi, la.bss
rend les exécutables plus petits et plus rapides à charger. Sinon, les variables pourrait être dans le.data
segment avec l'initialisation explicite de zéros; le programme aurait du mal à faire la différence. (Dans le détail, l'adresse des objets dans.bss
serait probablement différente de l'adresse si elle était dans l'.data
segment.)Dans le premier programme,
a
serait dans le.data
segment etb
serait dans le.bss
segment de l'exécutable. Une fois que le programme est chargé, la distinction devient immatériel. Au moment de l'exécution,b
occupe20 * sizeof(int)
octets.Dans le deuxième programme,
var
est alloué pour l'espace et l'affectation dansmain()
modifie l'espace. Il se trouve que l'espace pourvar
a été décrite dans le.bss
segment plutôt que de la.data
segment, mais cela n'affecte pas la façon dont le programme se comporte lors de l'exécution.static int i = 0
.static int i[100] = {1,2,3....}
.Alors mon exécutable 4*100 octets de plus grand. ?? Ou n'en.data
l'article, il ne dit où en mémoire le tableau statique serait stocké comme à partir de l'adresse0X00000000
à0x10232333
quelque chose comme ça. Vous avez dit.data
section est aussi grand que la somme des tailles des initialisé les variables.edata
). Dans la pratique, l' .sev n'existe pas en mémoire une fois le processus de l'image est terminé, la mise à zéro des données est assez simple .section de données. Mais les détails varient en fonction de l'o/s, etc.i
devront être stockées dans la section de données, car il doit être auto-contiguës, et il n'y a aucun moyen de s'assurer qu'il n'y a pas d'autres données initialisées avant et après elle, de sorte que la seule façon de s'assurer que les valeurs correctes sont stockés est de garder les 100int
(400 octets) de données dans la .les données de la section de l'exécutable. Si c'était le dernier tableau dans .de données, puis, en théorie, vous pouvez avoir 3int
initialiseurs dans .données et 97 des zéros .bss. Je peux prédire que cela n'arrive pas dans la vraie vie..data
section . Ou dans quelques section et il n'y aura pas.bss
Désolé, je me demande si beaucoup de question je veux juste que les choses dans ma tête. Aussi Pourriez-Vous suggérer certaines ressources comme le livre ou la chose pour l'étude de cette. Les pointeurs sur c livre comment est-il ?static int i[100] = {1,2,3,...}
est que tous les lieux sont initialisées à 1 , 2 ,3 et ainsi de suite.De Langage d'assemblage étape par Étape: Programmation avec Linux par Jeff Duntemann, concernant la .les données section:
et la .sev section:
Bien, tout d'abord, ces variables dans votre exemple ne sont pas initialisées; C indique que les variables statiques qui n'est pas autrement initialisé sont initialisées à 0.
Donc, la raison pour .l'option bss est d'avoir de petits fichiers exécutables, de gagner de l'espace et de permettre un chargement plus rapide du programme, le chargeur peut seulement attribuer un tas de zéros au lieu de copier les données à partir du disque.
Lors de l'exécution du programme, le programme chargeur charge .les données et les .sev dans la mémoire. Écrit dans les objets résidant dans .de données ou de .sev donc uniquement de la mémoire, elles ne sont pas vidées dans le binaire sur le disque en tout point.
La Système V ABI 4.1 (1997) (AKA ELFE de la spécification) contient également de la réponse:
dit que le nom de la section
.bss
est réservé et a des effets spéciaux, en particulier, il occupe pas d'espace fichier, donc l'avantage sur.data
.L'inconvénient est bien sûr que tous les octets doivent être mis à
0
lorsque le système d'exploitation met en mémoire, ce qui est plus restrictif, mais elles ont en commun de cas d'utilisation et fonctionne très bien pour les variables non initialisées.La
SHT_NOBITS
type de section de la documentation répète cette affirmation:Le C standard ne dit rien sur les articles, mais on peut facilement vérifier que la variable est stockée dans Linux avec
objdump
etreadelf
, et de conclure que les variables globales non initialisées sont en fait stockées dans le.bss
, voir par exemple cette réponse: https://stackoverflow.com/a/36725211/895245L'article de wikipédia .sev offre une belle explication historique, étant donné que le terme est à partir du milieu des années 1950 (youpi mon anniversaire;-).
Retour dans la journée, tout était précieux, de sorte que toute méthode de signalisation réservés vide de l'espace, a été utile. Ce (.sev) est celui qui a coincé.
.les données sections sont pour l'espace qui n'est pas vide, au contraire, il devra (vos) la définition des valeurs entré en elle.