Dalam segmen apa (.BSS, .DATA, lainnya) dari file yang dapat dieksekusi adalah variabel statis yang disimpan sehingga mereka tidak memiliki nama tabrakan? Sebagai contoh:
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);
} }
Jika saya mengkompilasi kedua file dan menautkannya ke utama yang memanggil fooTest () dan barTest berulang kali, pernyataan printf bertambah secara independen. Masuk akal karena variabel foo dan bar lokal untuk unit terjemahan.
Tetapi di mana penyimpanan dialokasikan?
Agar lebih jelas, asumsinya adalah Anda memiliki toolchain yang akan menampilkan file dalam format ELF. Jadi, saya percaya bahwa ada memiliki untuk beberapa ruang dicadangkan dalam file executable untuk variabel-variabel statis.
Untuk tujuan diskusi, mari kita asumsikan kita menggunakan GCC toolchain.
c++
c
compiler-construction
Benoit
sumber
sumber
Jawaban:
Ke mana statika Anda bergantung pada apakah statika tersebut diinisialisasi nol . data statis nol-diinisialisasi masuk .BSS (Blok Dimulai oleh Simbol) , data non-nol-diinisialisasi masuk .DATA
sumber
.data
, dan data statis tanpa inisialisasi masuk.bss
.Ketika sebuah program dimuat ke dalam memori, itu disusun dalam segmen yang berbeda. Salah satu segmen adalah segmen DATA . Segmen Data selanjutnya dibagi menjadi dua bagian:
Segmen data yang diinisialisasi: Semua data global, statis, dan konstan disimpan di sini.
Segmen data yang tidak diinisialisasi (BSS): Semua data yang tidak diinisialisasi disimpan di segmen ini.
Berikut ini diagram untuk menjelaskan konsep ini:
di sini ada tautan yang sangat bagus untuk menjelaskan konsep-konsep ini:
sumber
Faktanya, sebuah variabel adalah tuple (penyimpanan, ruang lingkup, jenis, alamat, nilai):
Lingkup lokal dapat berarti lokal untuk unit translasi (file sumber), fungsi atau blok tergantung di mana didefinisikan. Untuk membuat variabel terlihat lebih dari satu fungsi, itu pasti harus dalam DATA atau area BSS (tergantung pada apakah masing-masing diinisialisasi secara eksplisit atau tidak). Kemudian dicakup sesuai dengan semua fungsi atau fungsi dalam file sumber.
sumber
Lokasi penyimpanan data akan tergantung pada implementasi.
Namun, makna statis adalah "hubungan internal". Dengan demikian, simbol internal ke unit kompilasi (foo.c, bar.c) dan tidak dapat dirujuk di luar unit kompilasi. Jadi, tidak ada tabrakan nama.
sumber
di area "global dan statis" :)
Ada beberapa area memori di C ++:
Lihat di sini untuk jawaban terperinci untuk pertanyaan Anda:
sumber
Saya tidak percaya akan ada tabrakan. Menggunakan statis di tingkat file (fungsi luar) menandai variabel sebagai lokal ke unit kompilasi saat ini (file). Itu tidak pernah terlihat di luar file saat ini sehingga tidak pernah harus memiliki nama yang dapat digunakan secara eksternal.
Menggunakan statis di dalam suatu fungsi berbeda - variabel hanya terlihat oleh fungsi (apakah statis atau tidak), hanya saja nilainya dipertahankan di seluruh panggilan ke fungsi tersebut.
Akibatnya, statis melakukan dua hal berbeda tergantung di mana tempatnya. Namun dalam kedua kasus, visibilitas variabel terbatas sedemikian rupa sehingga Anda dapat dengan mudah mencegah bentrokan namespace saat menautkan.
Karena itu, saya percaya itu akan disimpan di
DATA
bagian, yang cenderung memiliki variabel yang diinisialisasi ke nilai selain nol. Ini, tentu saja, detail implementasi, bukan sesuatu yang diamanatkan oleh standar - itu hanya peduli tentang perilaku, bukan bagaimana hal-hal dilakukan di bawah selimut.sumber
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)?
Cara menemukannya sendiri
objdump -Sr
Untuk benar-benar memahami apa yang sedang terjadi, Anda harus memahami relokasi linker. Jika Anda belum pernah menyentuhnya, pertimbangkan untuk membaca posting ini terlebih dahulu .
Mari kita menganalisis contoh ELF Linux x86-64 untuk melihatnya sendiri:
Kompilasi dengan:
Dekompilasi kode dengan:
-S
mendekompilasi kode dengan sumber asli yang disatukan-r
menunjukkan informasi relokasiDi dalam dekompilasi
f
kita melihat:dan
.data-0x4
mengatakan bahwa itu akan pergi ke byte pertama dari.data
segmen tersebut.Ada di
-0x4
sana karena kita menggunakan pengalamatan RIP relatif, sehingga%rip
dalam instruksi danR_X86_64_PC32
.Ini diperlukan karena RIP menunjuk ke instruksi berikut , yang dimulai 4 byte dan setelah
00 00 00 00
itu apa yang akan dipindahkan. Saya telah menjelaskan ini secara lebih rinci di: https://stackoverflow.com/a/30515926/895245Kemudian, jika kita memodifikasi sumber ke
i = 1
dan melakukan analisis yang sama, kita menyimpulkan bahwa:static int i = 0
terus.bss
static int i = 1
terus.data
sumber
Ini caranya (mudah dimengerti):
sumber
Itu tergantung pada platform dan kompiler yang Anda gunakan. Beberapa kompiler menyimpan langsung di segmen kode. Variabel statis selalu hanya dapat diakses oleh unit terjemahan saat ini dan nama tidak diekspor sehingga alasan tabrakan nama tidak pernah terjadi.
sumber
Data yang dideklarasikan di unit kompilasi akan masuk ke .BSS atau .Data dari output file itu. Data diinisialisasi dalam BSS, tidak diinisialisasi dalam DATA.
Perbedaan antara data statis dan global datang dalam penyertaan informasi simbol dalam file. Compiler cenderung memasukkan informasi simbol tetapi hanya menandai informasi global seperti itu.
Tautan menghormati informasi ini. Informasi simbol untuk variabel statis dibuang atau dihancurkan sehingga variabel statis masih dapat dirujuk dengan beberapa cara (dengan opsi debug atau simbol). Dalam kedua kasus ini, unit kompilasi tidak akan terpengaruh ketika tautan menyelesaikan referensi lokal terlebih dahulu.
sumber
Saya mencobanya dengan objdump dan gdb, berikut ini hasilnya yang saya dapat:
di sini adalah hasil objdump
Jadi, bisa dikatakan, keempat variabel Anda berada di acara bagian data dengan nama yang sama, tetapi dengan offset yang berbeda.
sumber
variabel statis disimpan dalam segmen data atau segmen kode seperti yang disebutkan sebelumnya.
Anda dapat yakin bahwa itu tidak akan dialokasikan pada tumpukan atau tumpukan.
Tidak ada risiko tabrakan karena
static
kata kunci menentukan ruang lingkup variabel untuk menjadi file atau fungsi, dalam kasus tabrakan ada kompiler / penghubung untuk memperingatkan Anda tentang.A nice contoh
sumber
Yah pertanyaan ini agak terlalu tua, tetapi karena tidak ada yang menunjukkan informasi yang berguna: Periksa pos dengan 'mohit12379' menjelaskan penyimpanan variabel statis dengan nama yang sama di tabel simbol: http://www.geekinterview.com/question_details/ 24745
sumber
Jawabannya mungkin sangat tergantung pada kompiler, jadi Anda mungkin ingin mengedit pertanyaan Anda (maksud saya, bahkan gagasan segmen tidak diamanatkan oleh ISO C atau ISO C ++). Misalnya, pada Windows yang dapat dieksekusi tidak membawa nama simbol. Satu 'foo' akan diimbangi 0x100, yang lainnya mungkin 0x2B0, dan kode dari kedua unit terjemahan dikompilasi dengan mengetahui offset untuk foo "mereka".
sumber
keduanya akan disimpan secara independen, namun jika Anda ingin menjelaskannya kepada pengembang lain, Anda mungkin ingin membungkusnya dalam ruang nama.
sumber
Anda sudah tahu apakah itu menyimpan dalam bss (blok mulai dengan simbol) juga disebut sebagai segmen data yang tidak diinisialisasi atau di segmen data yang diinisialisasi.
mari kita ambil contoh sederhana
variabel statis di atas tidak diinisialisasi, jadi pergi ke segmen data yang tidak diinisialisasi (bss).
dan tentu saja diinisialisasi oleh 10 sehingga masuk ke segmen data yang diinisialisasi.
sumber