Belajar C++ - Memory & Resource Management
Episode 7 of 24

Belajar C++ - Memory & Resource Management

Episode ini membedah pointer dan reference, pointer arithmetic, alokasi dinamis dengan new dan delete serta smart pointer, pola RAII untuk resource management deterministik, dan bug memori umum seperti use-after-free dan double-free.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Inilah materi yang membedakan C++ dari hampir semua bahasa modern: kalian mengelola memori secara langsung. Kemampuan ini memberi kinerja dan kontrol luar biasa, tetapi juga menuntut tanggung jawab — salah kelola memori berarti crash, kebocoran, atau kerentanan keamanan.

Episode 7 membangun pemahaman menyeluruh tentang memori: apa itu pointer dan reference, bagaimana pointer arithmetic bekerja, bagaimana alokasi dinamis dikelola secara manual dan modern, mengapa RAII adalah pola terpenting di C++, serta bug-bug memori yang harus kalian kenali dan hindari.

Pointer dan Reference

Alamat dan Isi

Setiap variabel tinggal di alamat memori. Pointer menyimpan alamat itu; reference adalah alias yang mengikat ke variabel lain. Dereference *p membaca nilai di alamat yang ditunjuk:

Pointer dan reference
cat > ptr.cpp <<'EOF'
#include <iostream>
 
int main() {
    int x = 42;
    int* p = &x;
    int& r = x;
 
    std::cout << "x = " << x << "\n";
    std::cout << "Alamat x = " << p << "\n";
    std::cout << "Dereference = " << *p << "\n";
 
    *p = 99;
    r = 100;
    std::cout << "x setelah diubah = " << x << "\n";
}
EOF
g++ -std=c++20 ptr.cpp -o ptr
./ptr

int* p = &x menyimpan alamat x, dan int& r = x membuat alias r ke x. Pointer bisa bernilai nullptr dan bisa diubah menunjuk ke tempat lain; reference selalu terikat dan tidak pernah kosong.

Reference ke const

Kombinasi const dan pointer perlu dibaca hati-hati: const int* p berarti pointer ke int konstan, sedangkan int* const p berarti pointer konstan. Fungsi cetak(const std::string& s) menerima string tanpa menyalin dan tanpa mengubahnya — pola default untuk argumen tipe besar.

Pointer Arithmetic

Bergerak di Sepanjang Array

Pointer bisa dijumlahkan dan dikurangi. Menambah pointer sebesar satu memindahkannya ke elemen berikutnya — bukan byte berikutnya. Besaran langkah ditentukan oleh tipe elemen, jadi p + 1 pada int* maju beberapa byte sesuai ukuran int:

Iterasi array dengan pointer
cat > ptrarith.cpp <<'EOF'
#include <iostream>
 
int main() {
    int arr[]{10, 20, 30, 40};
    int* p = arr;
 
    for (int i = 0; i < 4; ++i) {
        std::cout << *(p + i) << " ";
    }
    std::cout << "\n";
 
    for (int* q = arr; q != arr + 4; ++q) {
        std::cout << *q << " ";
    }
    std::cout << "\n";
}
EOF
g++ -std=c++20 ptrarith.cpp -o ptrarith
./ptrarith

Pola for (int* q = arr; q != arr + 4; ++q) adalah iterasi pointer klasik. Di C++ modern, iterator dan range-based for menggantikan pola ini untuk data di kontainer, tetapi pointer arithmetic tetap esensial untuk pemrograman rendah tingkat.

Alokasi Dinamis dengan new dan delete

Alokasi Manual

Operator new mengalokasikan memori di heap dan memanggil constructor; delete memanggil destructor dan membebaskan memori. Setiap new wajib berpasangan dengan delete:

Alokasi dinamis manual
cat > manual.cpp <<'EOF'
#include <iostream>
 
int main() {
    int* p = new int(7);
    std::cout << *p << "\n";
    delete p;
 
    int* arr = new int[5];
    for (int i = 0; i < 5; ++i) {
        arr[i] = i * i;
    }
    std::cout << arr[3] << "\n";
    delete[] arr;
}
EOF
g++ -std=c++20 manual.cpp -o manual
./manual

new int(7) mengalokasikan satu int dengan nilai 7, dan new int[5] mengalokasikan array. Ingat pasangannya: delete untuk objek tunggal, delete[] untuk array. Mencampurnya adalah undefined behavior.

Mengapa Menghindari new Manual

Alokasi manual rawan: jika delete terlewat saat ada pengecualian atau return lebih awal, terjadi kebocoran. Jika delete dipanggil dua kali pada pointer yang sama, terjadi double-free. Solusi modern: jangan alokasikan manual — gunakan smart pointers dan kontainer STL yang mengelola memori sendiri.

RAII dan Smart Pointer

Resource Acquisition Is Initialization

RAII adalah pola inti C++: inisialisasi objek = perolehan resource, penghancuran objek = pelepasan resource. Dengan menempatkan resource di constructor dan melepaskannya di destructor, resource terjamin dibebaskan pada saat yang pasti — bahkan saat exception terjadi.

Smart Pointer sebagai RAII

std::unique_ptr, std::shared_ptr, dan std::weak_ptr menerapkan RAII untuk memori heap:

Smart pointer RAII
cat > raii.cpp <<'EOF'
#include <iostream>
#include <memory>
 
class Buffer {
public:
    explicit Buffer(size_t n) : data_(new int[n]) {}
    ~Buffer() { delete[] data_; }
    int* data() { return data_; }
 
private:
    int* data_;
};
 
int main() {
    auto buff = std::make_unique<Buffer>(10);
    buff->data()[0] = 5;
    std::cout << buff->data()[0] << "\n";
}
EOF
g++ -std=c++20 raii.cpp -o raii
./raii

std::make_unique<Buffer>(10) membuat Buffer yang isinya dibebaskan oleh destructor saat buff keluar dari scope. Tidak ada delete manual di main — RAII mengaturnya.

Bug Memori Umum

Use-after-free, Double-free, dan Dangling Pointer

Use-after-free terjadi saat kalian memakai memori setelah dibebaskan. Double-free terjadi saat delete dipanggil dua kali untuk alamat yang sama. Dangling pointer menunjuk ke memori yang sudah tidak valid — misalnya pointer ke variabel lokal yang sudah mati. Memakai memori yang sudah mati adalah undefined behavior, dan compiler dengan -Wall -Wextra akan memperingatkannya. Solusinya: kembalikan value, atau alokasikan dengan make_unique jika objek harus hidup lebih lama.

Info

Deteksi bug memori bisa diotomatisasi. Compile dengan -fsanitize=address untuk mendeteksi use-after-free dan overflow; episode 11 dan 15 akan membahas sanitizer dan Valgrind.

Penutup

Inti yang harus dibawa pulang:

  • Pointer menyimpan alamat; reference adalah alias yang tidak pernah kosong.
  • Pointer arithmetic bergerak per elemen, bukan per byte.
  • Setiap new berpasangan delete, setiap new[] berpasangan delete[].
  • RAII menghubungkan resource dengan umur objek.
  • Smart pointers menghapus kebutuhan new dan delete manual.
  • Use-after-free, double-free, dan dangling pointer adalah undefined behavior.

Di episode 8 selanjutnya kita akan membahas data structures dan STL containers — array, std::vector, std::array, dan std::deque, kontainer asosiatif std::set, std::map, dan std::unordered_map, iterator dan algoritma std::algorithm, serta container adaptors seperti stack, queue, dan priority_queue.

Belajar C++ - Memory & Resource Management | Belajar C++