Dari eksperimen Graydon Hoare 2006 sampai ekosistem Rust hari ini — lihat bagaimana keamanan memori tanpa garbage collector membentuk ulang pemrograman sistem.

Artikel ini menceritakan sebuah origin story yang fokus: bagaimana eksperimen pribadi Graydon Hoare berkembang menjadi Rust, dan mengapa pilihan desain Rust cukup penting untuk mengubah ekspektasi terhadap pemrograman sistem.
“Systems programming” berada dekat dengan mesin—dan dekat dengan risiko produk Anda. Ia muncul di peramban, mesin game, komponen sistem operasi, basis data, jaringan, dan perangkat lunak embedded—tempat-tempat di mana biasanya Anda memerlukan:
Secara historis, kombinasi itu mendorong tim ke C dan C++, plus aturan, review, dan tooling ekstensif untuk mengurangi bug terkait memori.
Janji headline Rust mudah diucapkan dan sulit diwujudkan:
Keamanan memori tanpa garbage collector.
Rust bertujuan mencegah kegagalan umum seperti use-after-free, double-free, dan banyak jenis race—tanpa mengandalkan runtime yang secara periodik menghentikan program untuk mengambil kembali memori. Sebagai gantinya, Rust memindahkan banyak pekerjaan itu ke waktu kompilasi melalui ownership dan borrowing.
Anda akan mendapatkan sejarah (dari gagasan awal sampai keterlibatan Mozilla) dan konsep kunci (ownership, borrowing, lifetimes, safe vs. unsafe) dijelaskan dalam bahasa sederhana.
Yang tidak Anda dapatkan adalah tutorial Rust lengkap, tur sintaksis penuh, atau panduan langkah-demi-langkah setup proyek. Anggap ini sebagai “mengapa” di balik desain Rust, dengan contoh singkat untuk membuat idenya konkret.
Catatan penulis: versi penuh menargetkan ~3.000 kata, memberi ruang untuk contoh singkat tanpa berubah menjadi manual referensi.
Rust tidak dimulai sebagai bahasa "pemenang" yang dirancang oleh komite. Ia bermula dari eksperimen pribadi Graydon Hoare pada 2006—pekerjaan yang ia kejar secara independen sebelum menarik perhatian lebih luas. Asal-usul itu penting: banyak keputusan desain awal tampak seperti upaya menyelesaikan rasa sakit sehari-hari, bukan untuk “menang” dalam teori bahasa.
Hoare mengeksplorasi cara menulis perangkat lunak tingkat-rendah dan berkinerja tinggi tanpa mengandalkan garbage collection—sambil menghindari penyebab crash dan bug keamanan paling umum di C dan C++. Ketegangan ini akrab bagi pemrogram sistem:
Arah “keamanan memori tanpa GC” Rust bukan awalnya slogan pemasaran. Itu adalah target desain: pertahankan karakteristik kinerja yang sesuai untuk kerja sistem, tetapi buat banyak kategori bug memori sulit untuk diekspresikan.
Wajar bertanya kenapa ini bukan "hanya kompiler yang lebih baik" untuk C/C++. Alat seperti analisis statis, sanitizer, dan library yang lebih aman mencegah banyak masalah, tetapi umumnya tidak bisa menjamin keamanan memori. Bahasa dasar mengizinkan pola yang sulit—atau tidak mungkin—diawasi sepenuhnya dari luar.
Taruhan Rust adalah memindahkan aturan kunci ke dalam bahasa dan sistem tipenya sehingga keselamatan menjadi hasil default, sambil tetap mengizinkan kontrol manual dalam jalur-jalur pelolosan yang jelas ditandai.
Beberapa detail tentang hari-hari awal Rust beredar sebagai anekdot (sering diulang dalam presentasi dan wawancara). Saat menceritakan origin story ini, membantu memisahkan tonggak yang didokumentasikan luas—seperti dimulainya pada 2006 dan adopsi Rust di Mozilla Research—dari kenangan pribadi dan penceritaan sekunder.
Untuk sumber primer, cari dokumentasi desain Rust awal, catatan desain, pembicaraan/wawancara Graydon Hoare, dan posting era Mozilla/Servo yang menjelaskan mengapa proyek diadopsi dan bagaimana tujuannya dibingkai. Bagian “baca lebih lanjut” yang solid bisa mengarahkan pembaca ke dokumen-dokumen asli (lihat /blog untuk tautan terkait).
Pemrograman sistem sering berarti bekerja dekat perangkat keras. Kedekatan itu membuat kode cepat dan efisien sumber daya. Tapi itu juga membuat kesalahan memori sangat menghukum.
Beberapa bug klasik muncul berulang kali:
Kesalahan-kesalahan ini tidak selalu jelas. Program bisa “berjalan” selama berminggu-minggu, lalu crash hanya di bawah pola input atau timing yang jarang.
Testing membuktikan sesuatu bekerja untuk kasus yang Anda uji. Bug memori sering bersembunyi di kasus yang Anda tidak uji: input yang tidak biasa, perangkat keras berbeda, perubahan kecil pada timing, atau versi kompiler baru. Mereka juga bisa non-deterministik—terutama pada program multi-threaded—sehingga bug menghilang saat Anda menambahkan logging atau memasang debugger.
Ketika memori salah, Anda tidak hanya mendapatkan error yang bersih. Anda mendapatkan status yang korup, crash yang tak terduga, dan kerentanan keamanan yang aktif dicari penyerang. Tim menghabiskan usaha besar mengejar kegagalan yang sulit direproduksi dan bahkan lebih sulit didiagnosis.
Perangkat lunak tingkat-rendah tidak selalu bisa “membayar” untuk keselamatan dengan pemeriksaan runtime berat atau pemindaian memori terus-menerus. Tujuannya lebih mirip meminjam alat dari bengkel bersama: Anda dapat menggunakannya bebas, tetapi aturannya harus jelas—siapa yang memegangnya, siapa yang boleh berbagi, dan kapan harus dikembalikan. Bahasa tradisional untuk sistem menyerahkan aturan-aturan itu pada disiplin manusia. Cerita asal Rust dimulai dengan mempertanyakan tradeoff itu.
Garbage collection adalah cara umum bahasa mencegah bug memori. Alih-alih memaksa Anda membebaskan memori, runtime melacak objek yang masih dapat dijangkau dan otomatis mereklamasi sisanya. Itu menghilangkan kategori masalah—use-after-free, double free, dan banyak kebocoran—karena program tidak bisa “lupa” membersihkan dengan cara yang sama.
GC tidaklah “buruk,” tetapi mengubah profil kinerja program. Sebagian besar kolektor memperkenalkan kombinasi:
Untuk banyak aplikasi—backend web, perangkat lunak bisnis, tooling—biaya itu dapat diterima atau bahkan tak terlihat. GC modern sangat baik dan meningkatkan produktivitas pengembang secara dramatis.
Dalam pemrograman sistem, kasus terburuk sering paling penting. Mesin peramban memerlukan rendering yang mulus; pengendali embedded mungkin punya batas waktu ketat; server latency-rendah dioptimalkan untuk menjaga tail latency tetap ketat di bawah beban. Di lingkungan ini, “biasanya cepat” kurang bernilai daripada “konsisten dapat diprediksi.”
Janji besar Rust: pertahankan kontrol seperti C/C++ atas memori dan tata letak data, tetapi berikan keamanan memori tanpa mengandalkan garbage collector. Tujuannya karakteristik kinerja yang dapat diprediksi—sambil membuat kode yang aman menjadi default.
Ini bukan argumen bahwa GC inferior. Ini taruhan bahwa ada ruang tengah penting: perangkat lunak yang membutuhkan kontrol tingkat-rendah dan jaminan keselamatan modern.
Ownership adalah ide besar paling sederhana Rust: setiap nilai memiliki satu pemilik yang bertanggung jawab membersihkannya ketika tidak lagi diperlukan.
Aturan tunggal itu menggantikan banyak pembukuan manual "siapa yang membebaskan ini?" yang sering diingat pemrogram C/C++ di kepala mereka. Alih-alih mengandalkan disiplin, Rust membuat pembersihan dapat diprediksi.
Saat Anda copy sesuatu, Anda berakhir dengan dua versi independen. Saat Anda move sesuatu, Anda menyerahkan yang asli—setelah move, variabel lama tidak lagi boleh menggunakannya.
Rust memperlakukan banyak nilai yang dialokasikan di heap (seperti string, buffer, atau vector) sebagai moved secara default. Menyalinnya seenaknya bisa mahal dan, lebih penting, membingungkan: jika dua variabel mengira mereka “pemilik” dari alokasi yang sama, Anda menyiapkan panggung untuk bug memori.
Berikut ide singkat dalam pseudo-code kecil:
buffer = make_buffer()
ownerA = buffer // ownerA owns it
ownerB = ownerA // move ownership to ownerB
use(ownerA) // not allowed: ownerA no longer owns anything
use(ownerB) // ok
// when ownerB ends, buffer is cleaned up automatically
(Blok kode di atas tidak diubah.)
Karena selalu ada tepat satu owner, Rust tahu persis kapan sebuah nilai harus dibersihkan: ketika pemiliknya keluar dari scope. Itu berarti manajemen memori otomatis (Anda tidak memanggil free() di mana-mana) tanpa perlu garbage collector yang memindai program saat runtime.
Aturan ownership ini memblokir kelas besar masalah klasik:
Model ownership Rust tidak hanya mendorong kebiasaan yang lebih aman—ia membuat banyak keadaan yang tidak aman tidak dapat direpresentasikan, yang menjadi fondasi fitur keselamatan Rust lainnya.
Ownership menjelaskan siapa “pemilik” sebuah nilai. Borrowing menjelaskan bagaimana bagian lain program dapat sementara menggunakan nilai itu tanpa mengambilnya.
Saat Anda meminjam sesuatu di Rust, Anda mendapatkan referensi ke situ. Pemilik asli tetap bertanggung jawab membersihkan memori; peminjam hanya mendapat izin untuk menggunakannya untuk sementara.
Rust memiliki dua jenis borrow:
&T): akses baca-saja.&mut T): akses baca-tulis.Aturan pinjam pusat Rust mudah diucapkan dan kuat dalam praktik:
Aturan ini mencegah kelas bug umum: satu bagian program membaca data sementara bagian lain mengubahnya di bawahnya.
Sebuah referensi hanya aman jika tidak pernah bertahan lebih lama daripada hal yang ditunjuknya. Rust menyebut durasi itu lifetime—jangka waktu di mana referensi dijamin valid.
Anda tidak perlu formalisme untuk memakai ide ini: sebuah referensi tidak boleh tetap ada setelah pemiliknya hilang.
Rust menegakkan aturan ini saat kompilasi melalui borrow checker. Alih-alih berharap testing menangkap referensi yang buruk atau mutasi berisiko, Rust menolak membangun kode yang dapat menggunakan memori dengan cara yang salah.
Bayangkan dokumen bersama:
Pemrograman sistem adalah pekerjaan yang berada dekat perangkat keras dan permukaan risiko produk—seperti mesin peramban, basis data, komponen OS, jaringan, dan perangkat embedded.
Biasanya menuntut kinerja yang dapat diprediksi, kontrol memori/tingkat-rendah, dan keandalan tinggi, di mana crash dan bug keamanan bisa sangat mahal.
Artinya Rust berusaha mencegah bug memori umum (seperti use-after-free dan double-free) tanpa bergantung pada garbage collector (GC).
Alih-alih runtime yang memindai dan mereklamasi memori saat program berjalan, Rust memindahkan banyak pengecekan keselamatan ke waktu kompilasi melalui aturan ownership dan borrowing.
Sanitizer dan analisis statis bisa menemukan banyak masalah, tapi biasanya mereka tidak bisa menjamin keselamatan memori jika bahasa itu sendiri membolehkan pola pointer dan lifetime yang berbahaya.
Rust memasukkan aturan kunci ke dalam bahasa dan sistem tipe sehingga kompiler bisa menolak kategori bug tertentu secara bawaan, sambil tetap menyediakan jalur keluar eksplisit saat perlu.
GC bisa menambah overhead runtime dan, yang lebih penting untuk beberapa beban kerja sistem, menghasilkan latensi yang kurang dapat diprediksi (mis. jeda atau kerja koleksi pada waktu yang tidak diinginkan).
Di domain seperti peramban, pengendali waktu-nyata, atau layanan latency-rendah, perilaku kasus terburuk penting—jadi Rust menargetkan keselamatan sambil mempertahankan karakteristik kinerja yang lebih dapat diprediksi.
Ownership berarti setiap nilai memiliki satu “penanggung jawab” (owner). Ketika owner keluar dari scope, nilai itu dibersihkan secara otomatis.
Ini membuat pembersihan menjadi dapat diprediksi dan mencegah situasi di mana dua tempat mengira mereka harus membebaskan alokasi yang sama.
Sebuah move mentransfer ownership dari satu variabel ke variabel lain; variabel asal tidak bisa lagi menggunakan nilai tersebut setelah dipindahkan.
Ini mencegah "dua pemilik" untuk satu alokasi, yang sering menjadi akar penyebab double-free dan use-after-free pada bahasa dengan manajemen memori manual.
Borrowing memungkinkan kode menggunakan sebuah nilai sementara melalui referensi tanpa mengambil ownership.
Aturan inti: banyak pembaca atau satu penulis—kamu bisa punya banyak referensi bersama (&T) atau satu referensi mutable (&mut T), tetapi tidak keduanya sekaligus. Ini mencegah banyak bug kelas mutation-while-reading dan aliasing.
Lifetime adalah “berapa lama sebuah referensi valid.” Rust mengharuskan referensi tidak pernah bertahan lebih lama daripada data yang ditunjuknya.
Borrow checker menegakkan ini saat kompilasi, sehingga kode yang dapat menghasilkan referensi menggantung (dangling) ditolak sebelum dijalankan.
Data race terjadi ketika beberapa thread mengakses memori yang sama secara bersamaan, setidaknya satu akses adalah write, dan tidak ada koordinasi.
Aturan ownership/borrowing Rust meluas ke konteks konkruensi sehingga pola sharing berbahaya sulit atau tidak mungkin diekspresikan dalam kode aman (safe). Itu mendorong penggunaan primitif sinkronisasi atau message passing yang eksplisit.
Sebagian besar kode ditulis dalam safe Rust, di mana kompiler menegakkan aturan keselamatan memori.
unsafe adalah jalur keluar yang jelas untuk operasi yang kompiler tidak bisa buktikan aman secara umum (mis. panggilan FFI atau primitif tingkat-rendah). Praktik umum: simpan unsafe kecil dan bungkus dengan API yang aman sehingga bagian yang berisiko mudah diaudit.