Mengapa buku mengatakan, "kompiler mengalokasikan ruang untuk variabel dalam memori". Bukankah itu executable yang melakukan itu? Maksud saya, misalnya, jika saya menulis program berikut,
#include <iostream>
using namespace std;
int main()
{
int foo;
return 0;
}
dan kompilasi, dan dapatkan executable (biarkan program.exe), sekarang, jika saya menjalankan program.exe, file yang dapat dieksekusi ini sendiri akan memerintahkan untuk mengalokasikan beberapa ruang untuk variabel foo. Bukan? Tolong jelaskan mengapa buku terus berkata, "kompiler akan melakukan ini ... lakukan itu".
sizeof
Pertanyaan sekarang terletak di Mengapa sizeof disebut operator saat kompilasi?Jawaban:
Anda benar bahwa kompiler seperti itu hilang ketika program Anda benar-benar berjalan. Dan jika itu berjalan pada mesin yang berbeda, kompiler bahkan tidak tersedia lagi.
Saya kira ini untuk membuat perbedaan yang jelas antara memori yang sebenarnya dialokasikan oleh kode Anda sendiri. Kompiler akan memasukkan beberapa kode dalam program Anda yang melakukan alokasi memori (seperti menggunakan perintah baru, malloc atau serupa).
Jadi buku menggunakan "kompiler melakukan ini atau itu" sering mengatakan kompiler menambahkan beberapa kode yang tidak secara eksplisit disebutkan dalam file kode Anda. Cukup benar bahwa ini tidak persis apa yang terjadi. Dari sudut pandang ini banyak hal yang disebutkan dalam tutorial akan salah tetapi akan membutuhkan penjelasan yang agak rumit.
sumber
malloc
et. Al.Itu tergantung pada variabelnya. OS mengalokasikan heap, program akan mengalokasikan stack dan kompiler akan mengalokasikan ruang untuk global / statika, yaitu mereka dibangun ke dalam exe itu sendiri. Jika Anda mengalokasikan 1MB memori global, ukuran exe Anda akan meningkat setidaknya 1MB
sumber
int test[256][1024]; int main(){ test[0][0]=2; return 0; }
program kecil ini memiliki 1MB dialokasikan tetapi hanya menghasilkan saya file objek 1,4 Kb dan 8,4 Kb dieksekusi. Ini harus menggunakan jumlah RAM yang benar.int a1=1,a2=2,
... semua jalan ke ..., a1048576=1048576;
Hanya dengan begitu Anda pasti akan mendapatkan sesuatu yang lebih besar dari 1mb saya pikir.apa kompilernya akan dilakukan adalah mengambil kode Anda dan mengkompilasinya ke dalam kode mesin. Apa yang Anda sebutkan adalah contoh yang baik di mana kompiler hanya perlu menerjemahkan.
Misalnya, ketika Anda menulis
Anda dapat melihat bahwa sebagai 'Saya memberi tahu kompiler untuk [ dalam output yang dihasilkannya ] meminta agar komputer mencadangkan ram yang cukup untuk int yang dapat saya referensi nanti. Kompiler mungkin akan menggunakan id sumber daya atau mekanisme untuk melacak foo di kode mesin, Anda bisa menggunakan foo dalam file teks alih-alih menulis perakitan!Hore !
Jadi Anda mungkin juga melihat ini karena kompiler sedang menulis surat ( atau mungkin novel / ensiklopedia ) untuk semua prosesor dan perangkat yang ditargetkan. Surat itu ditulis dalam sinyal biner yang (umumnya) dapat diterjemahkan ke prosesor yang berbeda dengan mengubah target. 'Huruf' dan / atau kombo apa pun dapat mengirimkan segala jenis permintaan dan / atau data - seperti tolong alokasikan ruang untuk variabel ini yang digunakan oleh programmer.
sumber
Mengatakan "kompiler mengalokasikan memori" mungkin secara faktual tidak akurat dalam arti literal, tetapi itu adalah metafora yang sugestif dengan cara yang benar.
Apa yang sebenarnya terjadi adalah bahwa kompiler membuat program yang mengalokasikan memori sendiri. Kecuali itu bukan program yang mengalokasikan memori, tetapi OS.
Jadi apa yang sebenarnya terjadi adalah bahwa kompiler membuat program yang menggambarkan persyaratan memorinya dan OS mengambil deskripsi itu dan menggunakannya untuk mengalokasikan memori. Kecuali bahwa OS adalah sebuah program, dan program tidak benar-benar melakukan apa-apa, mereka menggambarkan perhitungan yang dilakukan oleh CPU. Kecuali bahwa CPU benar-benar hanya sirkuit elektronik yang rumit, bukan homonculus kecil yang antropomorfis.
Tetapi masuk akal untuk berpikir tentang program dan kompiler dan CPU sebagai orang kecil yang hidup di dalam komputer, bukan karena mereka sebenarnya, tetapi karena itu adalah metafora yang cocok dengan otak manusia dengan baik.
Beberapa metafora bekerja dengan baik untuk menggambarkan hal-hal pada satu tingkat abstraksi, tetapi tidak berfungsi dengan baik pada tingkat lain. Jika Anda berpikir pada tingkat kompiler, masuk akal untuk menggambarkan tindakan menghasilkan kode yang akan mengakibatkan memori dialokasikan ketika program yang sedang dikompilasi sebenarnya dijalankan sebagai "mengalokasikan memori". Cukup dekat sehingga ketika kita berpikir tentang cara kerja kompiler, kita punya ide yang tepat, dan tidak terlalu bertele-tele sehingga kita lupa apa yang kita lakukan. Jika kami mencoba menggunakan metafora itu pada tingkat program yang dikompilasi berjalan, itu menyesatkan dengan cara yang aneh, yang Anda perhatikan.
sumber
Itu kompiler yang memutuskan di mana menyimpan variabel - bisa di stack atau register gratis. Apa pun keputusan penyimpanan yang dibuat oleh kompiler, kode mesin yang sesuai untuk mengakses variabel tersebut akan dihasilkan dan tidak dapat diubah dalam waktu berjalan. Dalam hal ini, kompiler bertugas mengalokasikan ruang untuk variabel dan program.exe akhir hanya bertindak secara membabi buta seperti zombie dalam waktu berjalan.
Sekarang, jangan bingung dengan manajemen memori dinamis yang berbeda seperti malloc, baru atau mungkin manajemen memori Anda sendiri. Kompiler berurusan dengan penyimpanan variabel dan akses tetapi tidak peduli apa arti nilai aktual dalam kerangka / pustaka lain. Sebagai contoh:
Dalam menjalankan waktu, malloc dapat mengembalikan nomor sewenang-wenang tetapi kompiler tidak peduli, yang penting adalah di mana menyimpan nomor itu.
sumber
Ungkapan yang lebih akurat adalah: - "kompiler memberitahu loader untuk memesan ruang untuk variabel"
Dalam lingkungan C-ish akan ada tiga jenis ruang untuk variabel: -
Pada memori tumpukan OS modern tidak akan benar-benar dicadangkan tetapi dialokasikan sesuai kebutuhan.
sumber
Ya, Anda benar, dalam hal ini (mendeklarasikan variabel dalam suatu fungsi), kalimat buku Anda mungkin salah: ketika Anda mendeklarasikan variabel dalam suatu fungsi, itu akan dialokasikan pada tumpukan saat memasuki fungsi. Bagaimanapun, kompiler harus mengoptimalkan situasi: jika fungsinya non-rekursif (
main()
adalah kandidat yang baik untuk itu), tidak apa-apa untuk "mengalokasikan" itu waktu kompilasi (pada BSS).(Jika Anda ingin tahu di mana variabel Anda berada, Anda dapat memeriksanya dengan cara yang kotor (jika Anda tidak ingin memeriksa struktur file obj, mengapa tidak?), Sehingga Anda dapat mendeklarasikan beberapa jenis variabel yang berbeda: konstan, statis, dinamis,
malloc()
-terokasi dll, dan menampilkan alamatnya (gunakan%X
formatterprintf()
untuk keterbacaan yang lebih baik). Variabel yang berada di tumpukan akan memiliki alamat memori yang sangat berbeda.)sumber
Satu-satunya hal yang dilakukan pada saat runtime adalah menabrak tumpukan poinbter dengan jumlah tertentu. Jadi kompilator memutuskan sebelumnya:
Yang ini bisa disebut "alokasi", tetapi tentu saja, selama waktu kompilasi, ia hanya mengambil tempat dalam model yang dimiliki oleh kompiler dari program yang sedang berjalan.
sumber