bss Segment in C

8

In einer der Antworten auf die Frage " In Bezug auf die bss Segment und Datensegment in Unix ", sehe ich die Erklärung zu bss wie folgt:

  

Bss ist speziell: .bss-Objekte nehmen in der Objektdatei keinen Platz ein, und durch Zusammenfassen aller Symbole, die nicht speziell initialisiert werden, können sie leicht auf Null gesetzt werden.

Aber wenn ich Größe für die Objektdatei verwende, wird diese aus dem Code generiert:

%Vor%

Ich habe folgendes

%Vor%

und sehen Sie, wie die bss auf der Grundlage nicht initialisierter Datenelemente mit globalem Geltungsbereich wächst. Kann also irgendjemand die erwähnte Aussage rechtfertigen?

    
Vivek Maran 09.10.2012, 10:52
quelle

4 Antworten

9

Wenn Sie stdio.h entfernen, ist Ihre Ausgabe wahrscheinlich aussagekräftiger. Lässt diese Bibliothek ignorieren, da sie interne Variablen enthält.

In Ihrem speziellen Fall passiert Folgendes:

%Vor%

Da dies eine Variable ist, die im Dateibereich in der statischen Speicherdauer zugewiesen ist, genau wie jede Variable, die als static deklariert ist. Der C-Standard erfordert, dass, wenn eine Variable mit statischer Speicherdauer nicht explizit vom Programmierer initialisiert wird, wie in diesem Fall, vor dem Start des Programms auf Null gesetzt werden muss. Alle diese Variablen werden in das Segment .bss eingefügt.

%Vor%

Diese Variable wird auch im Dateibereich zugewiesen, so dass sie auch eine statische Speicherdauer hat. Aber in diesem Fall wird es vom Programmierer initialisiert. Der C-Standard fordert, dass solche Variablen vor dem Programmstart auf den angegebenen Wert gesetzt werden. Solche Variablen werden im .data -Segment platziert.

%Vor%

Diese Variable hat eine automatische Speicherdauer (lokal). Der Compiler wird diese Variable wahrscheinlich optimieren, da sie keinen Zweck erfüllt. Aber nehmen wir an, dass solche Optimierung nicht stattfindet. Die Variable wird dann in Runtime zugewiesen, wenn der Bereich (Block), in dem sie sich befindet, ausgeführt wird und dann aufhört zu existieren, sobald der Bereich beendet ist (er geht außer Geltungsbereich). Es wird entweder auf dem Stack oder in einem CPU-Register zugewiesen. Mit anderen Worten, zur Zeit der Verknüpfung existiert diese Variable nur als Programmcode in der Form eines Assemblerbefehls, der sagt "schiebe einen Int auf den Stapel" und dann später "platziere einen Int vom Stapel".

Wie diese verschiedenen Arten von Variablen initialisiert werden, hängt vom System ab. In der Regel wird jedoch vor dem Aufruf von main ein Teil des Codes vom Compiler eingespeist. Dies ist eine übermäßige Vereinfachung, aber aus pädagogischen Gründen können Sie sich vorstellen, dass Ihr Programm tatsächlich so aussieht:

%Vor%

Daten: 4 bss: 4

Eingebettete Systeme mit echtem nichtflüchtigem Speicher funktionieren genau wie der obige Code, während RAM-basierte Systeme den Dateninitialisierungsteil möglicherweise anders lösen. bss funktioniert auf allen Systemen gleich.

Sie können leicht überprüfen, dass sie in verschiedenen Segmenten gespeichert sind, indem Sie das folgende Programm ausführen:

%Vor%

Sie werden sehen, dass "nicht vorhandene" Variablen an benachbarten Adressen zugewiesen werden, aber an anderen Adressen als die anderen Variablen. Gleiches mit "init" Variablen. "Lokale" Variablen können überall zugewiesen werden, so dass Sie irgendeine seltsame Adresse als Ergebnis dieser beiden erhalten.

    
Lundin 09.10.2012, 11:48
quelle
5

Ich kenne die Antwort nicht sicher, aber meine Vermutung ist:

Die Größe des BSS-Segments befindet sich in der Objektdatei und wird durch die Größe angezeigt - & gt; es muss schließlich zugewiesen werden.

Aber die Objektdatei wird nicht wachsen, wenn das Segment wächst.

    
DThought 09.10.2012 10:57
quelle
2

a.out ist wahrscheinlich keine Objektdatei, es ist wahrscheinlich eine ausführbare ELF - Datei. Verschiebbare Objekte, im Allgemeinen name .o, sind Zwischendateien, bevor die Verknüpfung erfolgt. Siehe die Option -c für gcc.

    
cdarke 09.10.2012 10:58
quelle
2

bss segment wächst, aber Sie brauchen dieses Segment nicht in Ihrer Binärdatei (siehe objcopy).

Wenn Sie also diesen Code in eine Art ROM schreiben würden, würde er dort keinen Platz beanspruchen, aber Platz im RAM benötigen (und Code, um ihn auf 0 zu initialisieren).

    
dbrank0 09.10.2012 11:56
quelle