Mengapa Aplikasi Anda Membutuhkan Heap Lebih Dari Stack

6

Komputer Anda tidak hanya memiliki RAM. Ia memiliki lanskap memori yang berantakan, terfragmentasi, dan terus berubah sehingga CPU berpura-pura tidak terbatas. Inilah realitas struktur data dinamis yang berjalan pada perangkat keras modern.

Stasiun kerja pada umumnya saat ini memiliki RAM fisik berukuran 16 hingga 64 megabita. Namun jangan biarkan angka kecil itu membodohi Anda. Melalui teknik yang disebut memori virtual, sistem menukar data antara RAM dan hard disk. CPU melihat ilusi. Diperkirakan ia memiliki 200 hingga 500 megabita ruang yang berdekatan. Ilusi itu berhasil. Kode berjalan. Namun ketika OS harus menggali ke dalam hard drive untuk mengambil satu halaman memori, semuanya melambat. Anda merasakannya di lag. Anda merasakannya di putaran kipas. Meskipun kinerjanya menurun, memori virtual adalah cara yang murah untuk “memperluas” RAM Anda. Ini adalah kompromi yang perlu.

Mari kita asumsikan semuanya bersih. Total ruang memori 50 megabyte. Tidak lebih. Tidak kurang. Ini anggarannya.

Sistem operasi memiliki blok 50 megabyte ini. Itu membagi kuenya. Tidak sama rata. Tidak pernah sama rata.

Pertama, ada kodenya. Instruksi yang dapat dieksekusi untuk setiap aplikasi yang sedang berjalan, ditambah kernel OS itu sendiri. Bagian ini statis. Itu tidak berubah selama program masih hidup. Berikutnya adalah variabel global. Ini adalah konstanta bersama dan tanda negara yang dapat disentuh oleh setiap bagian aplikasi. Mereka tersimpan dalam memori sejak aplikasi diluncurkan hingga aplikasi tersebut mati.

Lalu ada tumpukan.

Tumpukannya kaku. Itu tumbuh dan menyusut seiring dengan pemanggilan fungsi. Saat Anda memanggil suatu fungsi, variabel dan parameter lokalnya dimasukkan ke dalam tumpukan. Saat fungsinya kembali, fungsi tersebut akan dihilangkan. Tumpukan mengingat perintah panggilan. Ini memastikan Anda kembali ke tempat yang tepat. Namun ukurannya maksimal. Anda tidak dapat meminta tumpukan memori lebih banyak di tengah penerbangan. Jika Anda mencoba, tumpukannya akan meluap. Programnya mogok.

Ketika suatu program selesai, OS mengeluarkannya. Kode, global, ruang tumpukan—semuanya dihapus bersih. Memori itu didaur ulang. Sudah siap untuk program berikutnya.

Tapi inilah masalahnya. Pada saat tertentu, sekitar 50 persen dari ruang sebesar 50 megabyte tersebut mungkin tidak terpakai. Mengapa? Karena tumpukan hanya menampung apa yang sedang dieksekusi. Kode hanya berisi instruksi. Potongan memori yang tidak terpakai tersebar. Itu adalah lubang.

Sistem operasi mengambil lubang-lubang ini dan mengelompokkannya. Ini menyebut kumpulan kolektif ini sebagai the heap.

Di sinilah alokasi dinamis terjadi. Heap adalah satu-satunya tempat di memori di mana suatu program dapat meminta jumlah ruang yang tepat, tepat pada saat program membutuhkannya. Anda tidak mendeklarasikan array yang terdiri dari 1000 bilangan bulat pada waktu kompilasi. Anda tidak tahu apakah Anda membutuhkan 1000 atau 100,000. Anda menunggu. Anda menjalankan kodenya. Anda memutuskan bahwa Anda membutuhkan ruang itu. Kemudian Anda memanggil malloc.

malloc adalah singkatan dari alokasi memori. Itu mengambil satu blok dari tumpukan. Ini mengembalikan sebuah pointer. Anda menggunakan penunjuk itu. Setelah selesai, Anda menelepon gratis. Blok itu kembali ke dalam kolam.

Inilah perbedaan mendasar antara memori statis dan dinamis. Tumpukannya otomatis. Hal ini terkait dengan ruang lingkup. Tumpukannya manual. Itu terkait dengan niat.

Mengapa ini penting bagi Anda? Karena sebagian besar bug dalam perangkat lunak yang kompleks tidak berasal dari logika yang buruk. Mereka berasal dari manajemen memori yang buruk. Jika Anda mengalokasikan dari heap dan lupa mengosongkannya, Anda akan membocorkan memori. Tumpukannya menyusut. Akhirnya, sistem kehabisan ruang. Program terhenti. OS mematikan proses. Anda kehilangan pekerjaan yang belum disimpan.

Sebaliknya, jika Anda mencoba mengalokasikan terlalu banyak pada tumpukan, Anda akan melampaui batas tumpukan. Program ini berakhir secara tiba-tiba.

Tumpukan memungkinkan fleksibilitas. Hal ini memungkinkan struktur data berkembang. Daftar tertaut. Pohon. Grafik. Tak satu pun dari ini dapat ditentukan pada waktu kompilasi dengan ukuran tetap. Mereka harus dibangun dengan cepat. Mereka harus hidup di tumpukan.

Apakah tumpukannya sempurna? Tidak, itu pecahan. Saat Anda mengalokasikan dan membebaskan blok dengan ukuran berbeda, tumpukan tersebut menjadi teka-teki gambar dengan bagian yang hilang. Menemukan blok memori bebas yang berdekatan bisa menjadi lambat. Inilah sebabnya mengapa malloc terkadang membutuhkan banyak waktu. Ia harus mencari. Itu harus bersatu. Ia harus mengatasi kekacauan tersebut.

Namun tanpa heap, komputasi modern akan runtuh.