Linux contoh runnable minimal dengan analisis pembongkaran
Karena ini adalah detail implementasi yang tidak ditentukan oleh standar, mari kita lihat apa yang dilakukan kompiler pada implementasi tertentu.
Dalam jawaban ini, saya akan menautkan ke jawaban spesifik yang melakukan analisis, atau memberikan analisis langsung di sini, dan merangkum semua hasil di sini.
Semua itu ada dalam berbagai versi Ubuntu / GCC, dan hasilnya mungkin cukup stabil di seluruh versi, tetapi jika kita menemukan variasi mari kita tentukan versi yang lebih tepat.
Variabel lokal di dalam suatu fungsi
Baik itu mainatau fungsi lainnya:
void f(void) {
int my_local_var;
}
Seperti yang ditunjukkan di: Apa yang dimaksud dengan <value dioptimalkan keluar> di gdb?
-O0: tumpukan
-O3: register jika tidak tumpah, tumpuk sebaliknya
Untuk motivasi mengapa tumpukan ada, lihat: Apa fungsi instruksi push / pop yang digunakan pada register dalam rakitan x86?
Variabel global dan staticvariabel fungsi
/* BSS */
int my_global_implicit;
int my_global_implicit_explicit_0 = 0;
/* DATA */
int my_global_implicit_explicit_1 = 1;
void f(void) {
/* BSS */
static int my_static_local_var_implicit;
static int my_static_local_var_explicit_0 = 0;
/* DATA */
static int my_static_local_var_explicit_1 = 1;
}
- jika diinisialisasi
0atau tidak diinisialisasi (dan karena itu secara implisit diinisialisasi ke 0): .bssbagian, lihat juga: Mengapa segmen .bss diperlukan?
- jika tidak:
.databagian
char * dan char c[]
Seperti yang ditunjukkan pada: Di mana variabel statis disimpan dalam C dan C ++?
void f(void) {
/* RODATA / TEXT */
char *a = "abc";
/* Stack. */
char b[] = "abc";
char c[] = {'a', 'b', 'c', '\0'};
}
TODO akankah string string yang sangat besar juga diletakkan di tumpukan? Atau .data? Atau apakah kompilasi gagal?
Argumen fungsi
void f(int i, int j);
Harus melalui konvensi pemanggilan yang relevan, misalnya: https://en.wikipedia.org/wiki/X86_calling_conventions untuk X86, yang menentukan register spesifik atau lokasi stack untuk setiap variabel.
Lalu seperti yang ditunjukkan pada Apa yang dimaksud dengan <value dioptimalkan keluar> di gdb? , -O0kemudian mencelupkan semuanya ke tumpukan, sambil -O3mencoba menggunakan register sebanyak mungkin.
Namun, jika fungsinya digarisbawahi, mereka diperlakukan seperti penduduk lokal biasa.
const
Saya percaya bahwa tidak ada bedanya karena Anda dapat mengetikkannya.
Sebaliknya, jika kompiler dapat menentukan bahwa beberapa data tidak pernah ditulis, maka secara teori dapat menempatkannya .rodatabahkan jika bukan const.
Analisis TODO.
Pointer
Mereka adalah variabel (yang berisi alamat, yang merupakan angka), jadi sama dengan yang lainnya :-)
malloc
Pertanyaannya tidak masuk akal malloc, karena mallocmerupakan fungsi, dan dalam:
int *i = malloc(sizeof(int));
*i adalah variabel yang berisi alamat, jadi itu jatuh pada kasus di atas.
Adapun bagaimana malloc bekerja secara internal, ketika Anda menyebutnya kernel Linux menandai alamat tertentu sebagai dapat ditulis pada struktur data internal, dan ketika mereka disentuh oleh program pada awalnya, kesalahan terjadi dan kernel mengaktifkan tabel halaman, yang memungkinkan akses terjadi tanpa segfaul: Bagaimana cara kerja paging x86?
Namun perlu dicatat bahwa ini pada dasarnya persis seperti yang dilakukan execsyscall di bawah tenda ketika Anda mencoba menjalankan executable: ia menandai halaman yang ingin di-load, dan menulis program di sana, lihat juga: Bagaimana kernel mendapatkan file biner yang dapat dieksekusi berjalan di bawah linux? Kecuali itu execmemiliki beberapa batasan tambahan di mana memuat (misalnya kode tidak dapat dipindahkan ).
Syscall yang tepat digunakan untuk mallocadalah mmapdi yang modern 2020 implementasi, dan di masa lalu brkdigunakan: Apakah malloc () digunakan York () atau mmap ()?
Perpustakaan dinamis
Pada dasarnya mmaped ke memori: /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710
variabel envinroment dan main'sargv
Di atas tumpukan awal: /unix/75939/where-is-the-environment-string-actual-stored TODO mengapa tidak di. Data?