Tumpukan vs Gundukan

Saat program berjalan, data harus disimpan di memori. Ukuran ruang yang dipakai data serta lokasi penyimpanannya ditentukan oleh tipe data. Terdapat dua bagian memori yang dipakai untuk menampung data saat eksekusi program: Tumpukan (Stack) dan Gundukan (Heap).

Tumpukan (Stack)

Tumpukan adalah larik memori yang berurutan, mengikuti struktur data Masuk Terakhir Keluar Pertama (LIFO), dan menyimpan tiga jenis data berikut:

  • Nilai variabel dari beberapa tipe data
  • Konteks eksekusi program saat ini
  • Parameter yang dikirim ke dalam metode
Tumpukan mirip tabung koin, data hanya bisa dimasukkan dan dikeluarkan dari satu ujung saja.

Operasi memori pada tumpukan dikelola otomatis oleh sistem, pengembang tidak perlu mengaturnya secara manual. Memahami logika dasar tumpukan akan memudahkan Anda memahami alur eksekusi program dan dokumentasi resmi C#.

Karakteristik Utama Tumpukan

  • Hanya bisa menambah dan menghapus data di bagian paling atas tumpukan
  • Menyimpan data ke puncak tumpukan: Push
  • Mengambil data dari puncak tumpukan: Pop

Ciri Memori Tumpukan

  • Proses alokasi dan pelepasan memori sangat cepat, menggunakan ruang memori yang berurutan
  • Siklus hidup terikat pada pemanggilan metode: bingkai tumpukan akan terhapus otomatis setelah metode selesai dijalankan
  • Yang disimpan: variabel tipe nilai, parameter metode, variabel lokal, konteks eksekusi

Agar lebih mudah memahami cara kerja gundukan, mari kita lihat contoh kode sederhana

class Program
{
    static void Main(string[] args)
    {
        int a = 10;
        int b = 20;
        int sum = Add(a, b);
    }

    static int Add(int x, int y)
    {
        return x + y;
    }
}
Code language: JavaScript (javascript)

Logika contoh ini sangat sederhana. Dimulai dari baris pertama fungsi Main sebagai titik masuk program, kita buat variabel bertipe int bernama a, lalu baris kedua membuat variabel b. Baris ketiga memanggil fungsi Add dengan mengirimkan nilai a dan b ke dalam fungsi. Di dalam fungsi, x menerima nilai a dan y menerima nilai b, lalu fungsi mengembalikan hasil penjumlahan x + y yaitu 30 ke tempat pemanggilan untuk dimasukkan ke variabel sum. Setelah fungsi Add selesai berjalan, x dan y akan dikeluarkan dari tumpukan, nilai sum menjadi 30, lalu setelah Main selesai program akan keluar. Berikut kita bahas langkah demi langkah bagaimana seluruh proses ini berlangsung di dalam tumpukan.

Alur eksekusi program dan proses Push serta Pop pada tumpukan

Saat membuat variabel a, tipe dasar bawaan akan dialokasikan langsung di tumpukan dengan operasi Push
Jalankan baris kedua kode, buat variabel int kedua b dengan nilai 20. Data yang masuk duluan ada di bagian bawah tumpukan, data yang masuk kemudian ada di puncak tumpukan
Baris ketiga kode akan menjalankan Add(a,b) di sebelah kanan tanda sama dahulu untuk memanggil fungsi Add. Nilai a disalin ke x dan nilai b disalin ke y, ini hanya pengiriman nilai saja, a dan x adalah dua variabel terpisah yang tidak saling mempengaruhi.
Langkah ini hanya menghitung x + y lalu mengembalikan hasilnya, tidak perlu menyimpan hasilnya lama di tumpukan. Hasil 30 dikirim kembali ke tempat pemanggilan seperti penulisan int sum = 30;. Setelah perintah return x+y dijalankan, fungsi Add akan selesai dan semua variabel lokal di dalam fungsi akan diproses Pop. Pop akan menghapus ruang memori variabel tersebut agar bisa dipakai kembali nanti.
Posisi paling atas tumpukan disebut Puncak (Top), setelah Pop posisi puncak akan bergeser ke bawah.
Setelah Add selesai dijalankan, x dan y adalah parameter lokal milik Add sehingga akan diproses Pop satu per satu untuk mengosongkan ruang tumpukan agar sistem berjalan lancar.
Setelah Pop x dan y hilang, nilai 30 hasil kembalian Add dikirim ke tempat pemanggilan untuk dimasukkan ke sum.
Saat menjalankan int sum = 30 akan terjadi operasi Push kembali, variabel sum bernilai 30 diletakkan di puncak tumpukan. Setelah baris ini selesai, fungsi Main siap berakhir dan variabel lokal Main yaitu sum, b, a akan segera dihapus dengan operasi Pop.
Operasi Pop selalu dimulai dari bagian atas. Tumpukan seperti lorong satu arah dengan hanya satu pintu masuk dan keluar, semua data masuk dan keluar dari ujung yang sama. Oleh karena itu urutan penghapusan variabel di Main berbalik dari urutan pembuatan: sum duluan, lalu b, terakhir a.
Variabel b diproses Pop dan dihapus, penanda puncak tumpukan otomatis bergeser ke bawah.
Semua variabel sudah diproses Pop termasuk variabel terakhir a. Secara teliti fungsi Main masih memiliki variabel lokal lain yaitu larik string args dari Main(string[] args) yang berfungsi menampung argumen perintah saat menjalankan konsol. Data larik ini disimpan di dua bagian memori berbeda yang berkaitan dengan gundukan, kita tidak bahas args di demo ini agar lebih sederhana.

Ingat satu hal: saat fungsi berjalan variabel dibuat dari atas ke bawah dan dipush ke tumpukan dengan urutan a → b → masuk ke Add → x → y. Setelah Add selesai x dan y dipop, lalu sum dipush. Ketika Main berakhir variabel dihapus berbalik urutan pembuatan: sum, b, a.


Gundukan (Heap)

Gundukan adalah wilayah memori luas yang digunakan untuk mengalokasikan blok memori guna menampung objek data. Berbeda dengan tumpukan, data di gundukan bisa ditambah dan dihapus dengan urutan acak.

Program tidak bisa menghapus objek di gundukan secara manual, pembersihan objek yang tidak ada referensi dan tidak bisa diakses dilakukan otomatis oleh GC (Garbage Collector) milik CLR (Common Language Runtime). Hal ini menghindari kesalahan akibat pelepasan memori manual yang wajib dilakukan di bahasa pemrograman lain.

Gundukan bisa diibaratkan meja lebar yang bisa diisi barang sembarangan. Sedangkan tumpukan yang kita bahas sebelumnya mirip tabung koin yang hanya bisa masuk dan keluar dari satu ujung.

Gundukan seperti meja luas tanpa batas penempatan barang. Pengembang tidak perlu menghapus objek gundukan secara manual, semuanya dikelola GC. Jika suatu objek tidak ada bagian program yang menggunakannya lagi, GC akan menghapusnya secara berkala untuk membebaskan memori. Hal ini sangat meringankan beban pengembang dan mencegah program crash akibat kebocoran memori yang tidak dilepaskan. Bahasa seperti C++ mengharuskan pengembang melepaskan memori gundukan secara manual.

Alur Pembersihan GC

  1. Program membuat tiga objek di gundukan dan menyimpan referensi ke objek tersebut
  2. Program berhenti menggunakan salah satu objek sehingga semua referensi terputus
  3. GC mendeteksi objek tanpa referensi dan membebaskan memori yang dipakainya
  4. Pembersihan selesai, memori yang sudah dibebaskan bisa dialokasikan untuk objek baru

Ciri Memori Gundukan

  • Memori tidak berurutan, kecepatan alokasi lebih lambat dibanding tumpukan
  • Siklus hidup tidak terikat batas fungsi, dikelola secara terpusat oleh GC
  • Yang disimpan: instans tipe referensi (kelas, larik, delegat dll.), tumpukan hanya menyimpan alamat memori objek di gundukan

Mari kita lihat contoh agar lebih jelas. Seperti yang dijelaskan sebelumnya variabel lokal tipe dasar disimpan di tumpukan, sedangkan tipe buatan pengguna umumnya disimpan di gundukan. Berikut contoh kodenya:

class Program
{
    static void Main(string[] args)
    {
        int a = 10;
        int b = 20;
        Student tom = new Student("Tom", 12);
        Student lucy = new Student("Lucy", 12);
    }

}

class Student
{
    //Variabel anggota
    private string name;

    private int age;

    //Konstruktor, akan dibahas di bab selanjutnya
    public Student(string name, int age)
    {
        this.name = name;
        this.age = age;
    }

    //Metode anggota
    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {name}, Age: {age}");
    }
}   
Code language: JavaScript (javascript)

Gambar berikut menunjukkan skema penyimpanan empat variabel a, b, tom, lucy di dalam fungsi Main. Sama seperti penjelasan tumpukan sebelumnya, kode dijalankan dari atas ke bawah, variabel a dipush duluan lalu b. Nilai a dan b disimpan langsung di tumpukan.

Variabel tipe dasar disimpan langsung di tumpukan
Data tipe buatan Student disimpan di gundukan, sedangkan tumpukan hanya menyimpan alamat lokasi data di gundukan.
Contoh data tom tersimpan di blok gundukan 00001, tumpukan menyimpan alamat 00001 agar kita bisa menemukan data tersebut nantinya.

Setelah fungsi Main selesai dijalankan, referensi alamat lucy: 01010 di tumpukan akan dipop dan dihapus. Yang hilang hanya alamatnya saja, data objek asli di gundukan tetap ada. Saat ini objek di gundukan tidak lagi memiliki variabel di tumpukan yang mencatat alamatnya.

Objek Lucy di blok gundukan 01010 tidak ada lagi variabel di tumpukan yang menyimpan alamatnya, menjadi objek tanpa pemilik. GC akan menghapus objek ini di waktu yang tepat.
Objek Lucy di gundukan kehilangan semua referensi luar setelah alamat di tumpukan dipop. GC akan membersihkan memori objek ini kapan saja agar ruang bisa dipakai ulang. Selama masih ada bagian program yang mereferensikan objek, GC tidak akan menghapusnya.

Wilayah Memori

Tumpukan dan gundukan adalah pembagian memori di tingkat perangkat lunak, bukan pembagian fisik perangkat keras.

Tumpukan dan gundukan hanyalah pembagian logis memori yang dibuat software, perangkat keras RAM fisik tidak memiliki modul khusus yang bertanda “wilayah tumpukan” atau “wilayah gundukan”.

RAM fisik hanya berupa chip memori seragam dengan alamat fisik berurutan, tidak ada penanda khusus yang memisahkan tumpukan dan gundukan

Sistem operasi memberikan ruang memori virtual terpisah untuk setiap program yang berjalan, lalu membagi memori virtual ini menjadi empat segmen logis utama:

Segmen Kode: Menyimpan instruksi program hasil kompilasi

Segmen Statis Global: Variabel statis, konstanta

Segmen Tumpukan (Stack): Utas utama dan utas turunan program masing-masing memiliki blok tumpukan mandiri

Segmen Gundukan (Heap): Kumpulan memori bersama luas untuk alokasi dinamis

Tumpukan dan gundukan yang dibahas di sini hanyalah wilayah logis yang diberikan OS untuk setiap proses, tidak ada isolasi di tingkat perangkat keras.

Tumpukan vs Gundukan

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *