Halo! Selamat datang kembali di “Seri Belajar Dasar Pemrograman Bahasa C#“. Pada materi kali ini kita akan mempelajari dan mencoba memahami bagiamana data-data di dalam suatu variabel disimpan dan dialokasikan ke dalam memori. Kita akan mempelajari dua konsep alokasi memori di C#, yaitu stack dan heap.
Apa Itu Memori Komputer?
Semua aplikasi software menyimpan dan memanipulasi data di dalam memori komputer.
Memori komputer ini berfungsi sama seperti otak manusia, yaitu untuk menyimpan data dan instruksi dari suatu aplikasi komputer.
Ketika kita mendeklarasikan sebuah variabel, sebuah potongan memori akan dialokasikan untuk menyimpan dan memanipulasi nilai dari variabel tersebut. Potongan memori ini akan menyimpan tiga buah informasi, yaitu:
- Nama variabel
- Tipe data
- Nilai dari variabel tersebut.

Ada dua jenis pengalokasian memori berdasarkan dari tipe data yang disimpan, yaitu alokasi memori stack di mana data akan disimpan dalam alamat memori secara berurutan, serta alokasi memori heap di mana data akan disimpan tanpa mempertimbangkan urutan alamat memorinya.
Untuk mempermudah pemahaman Anda mengenai pengalokasian memori di stack dan heap, Anda bisa membayangkan memori stack seperti sebuah tumpukan kardus dan memori heap seperti sebuah loker.
Apa Itu Alokasi Memori Stack?
Ketika menumpuk sebuah kardus, kita biasanya memulainya dengan menumpuk dari bawah, kemudian menumpuk kardus yang lain di atasnya.
Ketika ingin mengambilnya, kita harus memulainya dari tumpukan paling atas dan seterusnya. Konsep ini dikenal dengan LIFO atau last in first out. Artinya, justru tumpukan terakhir (teratas) yang akan diambil pertama kali.

Stack sendiri dalam Bahasa Indonesia bisa diartikan sebagai suatu benda yang ditumpuk di atas suatu benda yang lain.
Bagaimana Sebuah Variabel Dialokasikan Di Stack?
Memori stack tidak jauh berbeda dengan analogi tumpukan kardus di atas. Setiap variabel yang dideklarasikan dengan tipe data yang termasuk value types, akan mendapat satu potong memori di stack yang nantinya akan dialokasikan dengan alamat yang berurutan.
Contohnya, apabila kita mendeklarasikan 3 buah variabel di dalam sebuah method, maka ketika method tersebut dipanggil, 3 potong memori di stack akan dialokasikan dengan alamat memori yang berurutan.
static void Main(string[] args)
{
// Memanggil method
sebuahMethod();
}
static void sebuahMethod()
{
// Instansiasi class Mobil / Membuat objek dari class Mobil
Mobil mobil = new Mobil();
// Deklarasi dan inisialisasi variabel lokal
int y = 2, x = 4;
}
Sederhananya, apabila alokasi memori untuk variabel pertama terletak di alamat x100, maka alokasi memori untuk variabel kedua terletak di alamat x101 dan variabel ketiga terletak di alamat x102.

Melihat Nilai Variabel Di Peta Memori Stack
Pada prakteknya, compiler akan mengalokasikan memori untuk setiap variabel dengan cara yang sedikit berbeda. Mari kita lihat bagaimana sebuah variabel sebenarnya dialokasikan di stack dengan memanfaatkan potongan kode program di bawah ini.
static void Main(string[] args)
{
byte x = 255;
int y = 8;
uint z = 4294967295;
}
Pada potongan kode program di atas, kita mendeklarasikan 3 buah variabel dengan tipe data yang berbeda-beda. Yaitu:
- Tipe data
byte
yang memiliki ukuran 1 byte, - tipe data
int
yang memiliki ukuran 4 byte, - dan terakhir tipe data
uint
yang memiliki ukuran 4 byte.
(Tabel tipe data dan ukurannya bisa Anda lihat di sini)
Apabila kita melakukan inspeksi pada memori stack, kita akan mendapatkan pemetaan memori seperti di bawah ini.

Yang perlu kita perhatikan dari gambar di atas adalah:
- kolom pertama merupakan alamat memori untuk setiap variabel yang disimpan, sedangkan kolom-kolom selanjutnya adalah nilai dari variabel tersebut.
- Satu kolom memiliki ukuran 1 Byte. Jadi untuk contoh di atas, setiap variabel memiliki alokasi memori sebesar 4 Byte (4 kolom).
Sebentar… bukankah tipe data byte
memiliki ukuran 1 Byte. Mengapa variabel yang seharusnya berukuran 1 Byte mendapat alokasi 4 Byte?
Ini terjadi karena kita menggunakan CPU dengan arsitektur x86 atau 32-bit (4 byte). Arsitektur ini memiliki smallest addressable unit atau unit terkecil yang bisa dialamatkan sebesar 4 byte.

Baiklah, sekarang coba kita lihat bagaimana masing-masing variabel di atas dialokasikan di stack.
- Pada saat variabel
x
dengan nilai 255 dialokasikan, nilai variabel tersebut akan disimpan di alamat memori 0x0726E8F4. Meskipun variabel ini sebenarnya hanya berukuran 1 byte, tapi memori yang dialokasikan adalah sebesar 4 byte, yaitu dari 0x0726E8F4 sampai 0x0726E8F7. - Pada saat variabel
y
dengan nilai 8 dialokasikan, nilai tersebut disimpan di alamat memori 0x0726E8F0 dan mengambil 4 Byte memori dari 0x0726E8F0 sampai 0x0726E8F3. - Terakhir pada saat variabel
z
dengan nilai 4294967295 (FFFFFFFF jika dinyatakan dengan Hexadesimal) dialokasikan, nilai tersebut disimpan di alamat memori 0x0726E8EC dan mengambil 4 Byte memori dari 0x0726E8EC sampai 0x0726E8EF.
Catatan
Alamat memori yang ditampilkan akan berubah-rubah setiap kali Anda meng-compile aplikasi Anda.
Di sini kita melihat bahwa variabel x
menempati alamat memori terbawah (baris ketiga) di stack, lalu variabel y
menempati alamat memori di atasnya (baris kedua), dan terakhir variable z
yang dideklarasikan terakhir menempati alamat memori teratas di stack (baris pertama).
Apa Itu Memori Heap?
Apabila Anda bisa menganalogikan memori stack seperti tumpukan kardus, sekarang Anda bisa menganalogikan memori heap seperti sebuah loker.

Apa yang bisa Anda bayangkan ketika menyimpan sesuatu di dalam loker?
Benar… Anda bebas menyimpan barang di pintu loker mana saja selama loker tersebut kosong. Pada saat mengambil barang, Anda juga tidak perlu mengeluarkan barang-barang yang disimpan di pintu loker yang lain.
Heap sendiri dalam Bahasa Indonesia kurang lebih juga bisa diartikan sebagai tumpukan. Namun berbeda dengan stack, heap adalah tumpukan yang tidak teratur. Seperti… tumpukan baju kotor (tumpukan baju di lemari bisa dianalogikan sebagai stack).
Ketika kita mendeklarasikan variabel dengan tipe data yang merupakan reference type seperti string
, sebenarnya variabel tersebut tetap akan disimpan di stack.
Sebentar.. bukannya reference type disimpan di heap?
Betul! Yang disimpan di heap adalah nilai sebenarnya dari variabel tersebut, sedangkan variabelnya tetap disimpan di stack.
Untuk lebih memahaminya, perhatikan deklarasi variabel di bawah ini.
string str = "Halo";
Pada deklarasi di atas, variabel str
akan dialokasikan di stack. Kemudian “Halo” akan disimpan di suatu lokasi di heap. Setelah lokasi teks “Halo” di heap ditentukan, alamat lokasi di mana teks “Halo” disimpan ini lah yang kemudian diberikan ke variabel str
. Sehingga, variabel str
di stack hanya akan menyimpan alamat lokasi di mana teks “Halo” sebenarnya disimpan. Nilai variabel str
di stack merupakan referensi dari nilai variabel str
di heap.

Alokasi memori untuk deklarasi variable str
di atas, bisa dilihat dari gambar di bawah ini.

Membebaskan Ruang Memori (Dealokasi)
Setelah data-data yang kita simpan di memori selesai digunakan, data-data tersebut perlu dihapus agar lokasi memori yang diambil bisa dipakai oleh data-data lain yang akan digunakan.
Data-data yang tersimpan di stack akan dihapus secara otomatis setelah method di mana variabel yang menyimpan data-data tersebut selesai dieksekusi.
Untuk lebih memahaminya, perhatikan potongan kode program di bawah ini.
static void Main(string[] args)
{
SebuahMethod();
}
static void SebuahMethod()
{
string str = "Halo";
int x = 255;
} //akhir dari SebuahMethod()
Seperti yang sudah Anda pelajari, baik variabel str
maupun x
akan dialokasikan di stack ketika SebuahMethod()
dipanggil. Setelah method tersebut selesai dieksekusi, maka data-data variabel str
dan x
di stack akan secara otomatis dihapus. Ruang memori yang tadinya terpakai, kini bebas digunakan kembali untuk kegunaan yang lain.
Masalahnya, nilai str
yang tersimpan di stack hanya merupakan alamat di mana nilai str
sebenarnya yang disimpan di heap, bukan nilainya itu sendiri. Nilai yang tersimpan di heap tidak akan dihapus secara otomatis meskipun variabel yang menyimpan referensi ke nilai tersebut sudah dihapus.
Sebagai programmer di platform .NET, kita bisa sedikit lega. Kita tidak perlu bingung memikirkan bagaimana caraya melakukan dealokasi memori di heap. Nantinya, Garbage Collector dari .NET akan mengurus semuanya untuk Anda.
Catatan
Pengelolaan memori di C# merupakan topik yang sangat kompleks dan luas. Penjelasan tentang bagaimana garbage collector bekerja berada di luar pembahasan materi kali ini.
Penutup
Pada materi kali ini kita sudah mempelajari tentang bagaimana data-data di dalam sebuah variabel dialokasikan dan disimpan di dalam memori stack dan heap.
Setiap variabel yang dideklarasikan akan disimpan di dalam memori stack. Namun, apabila sebuah variabel mempunyai nilai dari tipe data yang merupakan reference type, maka nilai sebenarnya akan disimpan di memori heap. Sementara nilai variabelnya yang disimpan di stack hanya berisi referensi atau alamat lokasi di mana nilai sebenarnya disimpan.
Data-data yang disimpan di memori stack akan otomatis dihapus ketika method di mana variabel tersebut dideklarasikan telah selesai dieksekusi. Sedangkan Garbage Collector milik .NET akan melakukan dealokasi memori heap.
Apabila Anda mempunyai pertanyaan seputar materi di tulisan ini, silahkan tinggalkan pertanyaan Anda di kolom komentar.
Selamat belajar!
Akhirnya paham juga saya. kebetulan lagi belajar assembly. terimakasih.
Halo Mas Ady,
Sama-sama, Mas.. Senang materi ini bisa membantu pemahaman Mas Ady..