Dengan mempertimbangkan bahwa memori dibagi menjadi empat segmen: data, heap, stack, dan kode, di mana melakukan variabel global, variabel statis, tipe data konstan, variabel lokal (didefinisikan dan dinyatakan dalam fungsi), variabel (dalam fungsi utama), pointer , dan ruang yang dialokasikan secara dinamis (menggunakan malloc dan calloc) disimpan dalam memori?
Saya pikir mereka akan dialokasikan sebagai berikut:
- Variabel global -------> data
- Variabel statis -------> data
- Tipe data konstan -----> kode
- Variabel lokal (dideklarasikan dan didefinisikan dalam fungsi) --------> stack
- Variabel dideklarasikan dan didefinisikan dalam fungsi utama -----> heap
- Pointer (misalnya
char *arr
,,int *arr
) -------> heap - Ruang yang dialokasikan secara dinamis (menggunakan malloc dan calloc) --------> tumpukan
Saya merujuk ke variabel-variabel ini hanya dari perspektif C.
Harap perbaiki saya jika saya salah karena saya baru mengenal C.
c
memory
memory-management
types
starkk92
sumber
sumber
main
hanyalah fungsi lain. Variabel masuk stack kecualimalloc
hanya seperti di tempat lain.Jawaban:
Anda benar, tetapi siapa pun yang menulis pertanyaan itu menipu Anda pada setidaknya satu pertanyaan:
main
fungsi ----->heapjuga menumpuk (guru sedang mencoba menipu Anda)char *arr
,int *arr
) ------->tumpukandata atau stack, tergantung pada konteks. C memungkinkan Anda mendeklarasikan global ataustatic
pointer, dalam hal ini pointer itu sendiri akan berakhir di segmen data.malloc
,calloc
,realloc
) -------->tumpukantumpukanPerlu disebutkan bahwa "tumpukan" secara resmi disebut "kelas penyimpanan otomatis".
sumber
alloca
yang bekerja mirip denganmalloc
, tetapi melakukan alokasi stack.Bagi pengunjung masa depan yang mungkin tertarik mengetahui tentang segmen memori tersebut, saya menulis poin penting tentang 5 segmen memori di C:
Beberapa kepala:
5 Segmen Memori dalam C:
1. Segmen Kode
printf("Hello, world")
maka string "Halo, dunia" akan dibuat di segmen kode / teks. Anda dapat memverifikasi ini menggunakansize
perintah di OS Linux.Segmen Data
Segmen data dibagi dalam dua bagian di bawah ini dan biasanya terletak di bawah area tumpukan atau dalam beberapa implementasi di atas tumpukan, tetapi segmen data tidak pernah terletak di antara area tumpukan dan tumpukan.
2. Segmen data yang tidak diinisialisasi
int globalVar;
atau variabel lokal statisstatic int localStatic;
akan disimpan di segmen data yang tidak diinisialisasi.0
atauNULL
masih tetap akan pergi ke segmen data yang tidak diinisialisasi atau bss.3. Segmen data yang diinisialisasi
int globalVar = 1;
atau variabel lokal statisstatic int localStatic = 1;
akan disimpan di segmen data yang diinisialisasi.4. Segmen Stack
5. Segmen Heap
malloc
,calloc
ataurealloc
metode.int* prt = malloc(sizeof(int) * 2)
delapan byte akan dialokasikan di heap dan alamat memori lokasi itu akan dikembalikan dan disimpan dalamptr
variabel. Theptr
variabel akan baik pada tumpukan atau data segmen tergantung pada cara dinyatakan / digunakan.sumber
Koreksi kalimat salah Anda
variabel konstan lokal -----> stack
variabel konstan global yang diinisialisasi -----> segmen data
variabel konstan global tidak diinisialisasi -----> bss
variabel dideklarasikan dan didefinisikan dalam fungsi utama -----> stack
pointer (mis: char * arr, int * arr) -------> ukuran variabel pointer akan berada di stack.
Pertimbangkan bahwa Anda mengalokasikan memori n byte (menggunakan
malloc
ataucalloc
) secara dinamis dan kemudian membuat variabel pointer untuk mengarahkannya. Sekarangn
byte memori berada di heap dan variabel pointer memerlukan 4 byte (jika mesin 64 bit 8 byte) yang akan di stack untuk menyimpan pointer mulai darin
byte byte memori.Catatan: Variabel pointer dapat menunjukkan memori segmen apa pun.
ruang yang dialokasikan secara dinamis (menggunakan malloc, calloc) --------> heap
sumber
Arsitektur desktop yang populer membagi memori virtual suatu proses dalam beberapa segmen :
Segmen teks: berisi kode yang dapat dieksekusi. Penunjuk instruksi mengambil nilai dalam rentang ini.
Segmen data: berisi variabel global (yaitu objek dengan tautan statis). Dibagi dalam data read-only (seperti konstanta string) dan data yang tidak diinisialisasi ("BSS").
Segmen tumpukan: berisi memori dinamis untuk program, yaitu toko bebas ("tumpukan") dan bingkai tumpukan lokal untuk semua utas. Secara tradisional tumpukan C dan tumpukan C dulu tumbuh ke segmen tumpukan dari ujung yang berlawanan, tapi saya percaya bahwa praktik telah ditinggalkan karena terlalu tidak aman.
Program AC biasanya menempatkan objek dengan durasi penyimpanan statis ke dalam segmen data, objek yang dialokasikan secara dinamis di toko bebas, dan objek otomatis pada tumpukan panggilan dari utas tempat ia tinggal.
Pada platform lain, seperti mode real x86 lama atau pada perangkat yang disematkan, segalanya dapat sangat berbeda.
sumber
Dari perspektif bahasa C , yang penting adalah luas, cakupan, keterkaitan, dan akses; persis bagaimana item dipetakan ke segmen memori yang berbeda hingga implementasi individu, dan itu akan bervariasi. Standar bahasa tidak berbicara tentang segmen memori sama sekali . Kebanyakan arsitektur modern kebanyakan bertindak dengan cara yang sama; variabel blok ruang lingkup dan argumen fungsi akan dialokasikan dari tumpukan, ruang lingkup file dan variabel statis akan dialokasikan dari segmen data atau kode, memori dinamis akan dialokasikan dari tumpukan, beberapa data konstan akan disimpan dalam segmen hanya-baca , dll.
sumber
Satu hal salah satu kebutuhan yang perlu diingat tentang penyimpanan adalah sebagai-jika aturan . Kompiler tidak diharuskan untuk meletakkan variabel di tempat tertentu - melainkan dapat menempatkannya di tempat yang diinginkan selama program yang dikompilasi berperilaku seolah-olah dijalankan di mesin C abstrak sesuai dengan aturan mesin C abstrak. Ini berlaku untuk semua durasi penyimpanan . Sebagai contoh:
42
dalam kode perakitan yang dihasilkan tetapi tidak ada tanda404
.const
atau secara efektifconst
tidak perlu berada dalam memori. Contoh - kompiler dapat membuktikan bahwafoo
secara efektifconst
dan inline penggunaannya ke dalam kode.bar
memiliki tautan eksternal dan kompiler tidak dapat membuktikan bahwa itu tidak akan diubah di luar modul saat ini, oleh karena itu tidak diuraikan.malloc
tidak perlu berada dalam memori yang dialokasikan dari tumpukan! Contoh - perhatikan bagaimana kode tidak memiliki panggilan kemalloc
dan nilai 42 tidak pernah disimpan dalam memori, ia disimpan dalam register!malloc
dan referensi hilang tanpa deallocating objek denganfree
tidak perlu membocorkan memori ...malloc
tidak perlu berada di dalam tumpukan di bawah program break (sbrk(0)
) pada Unixen ...sumber
Tidak, mereka bisa di stack atau di segmen data. Mereka dapat menunjuk ke mana saja.
sumber
main
dan variabel yang dialokasikan secara dinamis juga salahsumber
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
main
atau fungsi lainnya:Seperti yang ditunjukkan di: Apa yang dimaksud dengan <value dioptimalkan keluar> di gdb?
-O0
: tumpukan-O3
: register jika tidak tumpah, tumpuk sebaliknyaUntuk motivasi mengapa tumpukan ada, lihat: Apa fungsi instruksi push / pop yang digunakan pada register dalam rakitan x86?
Variabel global dan
static
variabel fungsi0
atau tidak diinisialisasi (dan karena itu secara implisit diinisialisasi ke0
):.bss
bagian, lihat juga: Mengapa segmen .bss diperlukan?.data
bagianchar *
danchar c[]
Seperti yang ditunjukkan pada: Di mana variabel statis disimpan dalam C dan C ++?
TODO akankah string string yang sangat besar juga diletakkan di tumpukan? Atau
.data
? Atau apakah kompilasi gagal?Argumen fungsi
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? ,
-O0
kemudian mencelupkan semuanya ke tumpukan, sambil-O3
mencoba 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
.rodata
bahkan 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
, karenamalloc
merupakan fungsi, dan dalam:*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
exec
syscall 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 ituexec
memiliki beberapa batasan tambahan di mana memuat (misalnya kode tidak dapat dipindahkan ).Syscall yang tepat digunakan untuk
malloc
adalahmmap
di yang modern 2020 implementasi, dan di masa lalubrk
digunakan: Apakah malloc () digunakan York () atau mmap ()?Perpustakaan dinamis
Pada dasarnya
mmap
ed ke memori: /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710variabel envinroment dan
main
'sargv
Di atas tumpukan awal: /unix/75939/where-is-the-environment-string-actual-stored TODO mengapa tidak di. Data?
sumber