Yang saya tahu adalah bahwa variabel global dan statis disimpan di .data
segmen, dan data yang tidak diinisialisasi ada di .bss
segmen tersebut. Yang tidak saya mengerti adalah mengapa kami memiliki segmen khusus untuk variabel yang tidak diinisialisasi? Jika variabel yang tidak diinisialisasi memiliki nilai yang ditetapkan pada waktu proses, apakah variabel tersebut masih ada di .bss
segmen saja?
Dalam program berikut, a
ada di .data
segmen, dan b
di .bss
segmen; Apakah itu benar? Mohon koreksi saya jika pemahaman saya salah.
#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 ()
{
;
}
Juga, pertimbangkan program berikut,
#include <stdio.h>
#include <stdlib.h>
int var[10]; /* Uninitialized so in .bss */
int main ()
{
var[0] = 20 /* **Initialized, where this 'var' will be ?** */
}
c
linux
compiler-construction
Siapa saya
sumber
sumber
Jawaban:
Alasannya adalah untuk mengurangi ukuran program. Bayangkan bahwa program C Anda berjalan pada sistem tertanam, di mana kode dan semua konstanta disimpan dalam ROM yang sebenarnya (memori flash). Dalam sistem seperti itu, "penyalinan" awal harus dijalankan untuk menyetel semua objek durasi penyimpanan statis, sebelum main () dipanggil. Biasanya akan seperti ini semu:
Di mana .data dan .bss disimpan di RAM, tetapi init_value disimpan di ROM. Jika tadinya satu segmen, maka ROM harus diisi dengan banyak angka nol, meningkatkan ukuran ROM secara signifikan.
Eksekutabel berbasis RAM bekerja dengan cara yang sama, meskipun tentu saja mereka tidak memiliki ROM yang sebenarnya.
Selain itu, memset kemungkinan merupakan assembler sebaris yang sangat efisien, yang berarti bahwa penyalinan awal dapat dijalankan lebih cepat.
sumber
The
.bss
segmen adalah optimasi. Seluruh.bss
segmen dideskripsikan dengan satu angka, mungkin 4 byte atau 8 byte, yang memberikan ukurannya dalam proses yang sedang berjalan, sedangkan.data
bagian tersebut sebesar jumlah ukuran variabel yang diinisialisasi. Dengan demikian,.bss
membuat executable lebih kecil dan lebih cepat dimuat. Jika tidak, variabel dapat berada di.data
segmen dengan inisialisasi eksplisit menjadi nol; program akan kesulitan untuk membedakannya. (Secara rinci, alamat objek di.bss
mungkin akan berbeda dari alamat jika berada di.data
segmen tersebut.)Pada program pertama,
a
akan berada di.data
segmen danb
akan berada di.bss
segmen yang dapat dieksekusi. Setelah program dimuat, perbedaannya menjadi tidak penting. Saat menjalankan,b
menempati20 * sizeof(int)
byte.Dalam program kedua,
var
dialokasikan ruang dan tugas dalammain()
memodifikasi ruang itu. Kebetulan ruang untukvar
dijelaskan di.bss
segmen daripada.data
segmen, tetapi itu tidak memengaruhi cara program berperilaku saat berjalan.sumber
edata
). Dalam istilah praktis, .bss tidak ada dalam memori setelah image proses selesai; data yang dibidik adalah bagian sederhana dari bagian .data. Tetapi detailnya bervariasi tergantung pada o / s dll.Dari Bahasa Perakitan Langkah-demi-Langkah: Pemrograman dengan Linux oleh Jeff Duntemann, terkait bagian .data :
dan bagian .bss :
sumber
Pertama-tama, variabel tersebut dalam contoh Anda tidak diinisialisasi; C menentukan bahwa variabel statis yang tidak diinisialisasi diinisialisasi ke 0.
Jadi, alasan untuk .bss adalah memiliki file executable yang lebih kecil, menghemat ruang dan memungkinkan pemuatan program yang lebih cepat, karena pemuat hanya dapat mengalokasikan sejumlah nol daripada harus menyalin data dari disk.
Saat menjalankan program, program loader akan memuat .data dan .bss ke dalam memori. Menulis ke objek yang berada dalam .data atau .bss sehingga hanya masuk ke memori, mereka tidak dipindahkan ke biner pada disk kapan pun.
sumber
The System V ABI 4.1 (1997) (AKA ELF spesifikasi) juga mengandung jawabannya:
mengatakan bahwa nama bagian
.bss
dicadangkan dan memiliki efek khusus, khususnya tidak menempati ruang file , sehingga lebih menguntungkan.data
.Kelemahannya tentu saja bahwa semua byte harus diatur ke
0
saat OS menempatkannya di memori, yang lebih membatasi, tetapi kasus penggunaan umum, dan berfungsi dengan baik untuk variabel yang tidak diinisialisasi.The
SHT_NOBITS
bagian jenis dokumentasi mengulangi penegasan bahwa:Standar C tidak mengatakan apa-apa tentang section, tetapi kita dapat dengan mudah memverifikasi di mana variabel disimpan di Linux dengan
objdump
danreadelf
, dan menyimpulkan bahwa global yang tidak diinisialisasi sebenarnya disimpan di.bss
. Lihat misalnya jawaban ini: Apa yang terjadi pada variabel yang dideklarasikan dan tidak diinisialisasi di C?sumber
Artikel wikipedia .bss memberikan penjelasan sejarah yang bagus, mengingat istilah tersebut berasal dari pertengahan tahun 1950-an (yippee my birthday ;-).
Dulu, setiap bit berharga, jadi metode apa pun untuk memberi sinyal pada ruang kosong yang dicadangkan, berguna. Ini ( .bss ) adalah salah satu yang macet.
Bagian .data adalah untuk ruang yang tidak kosong, melainkan akan memiliki nilai yang ditentukan (Anda) dimasukkan ke dalamnya.
sumber