POINTER: DYNAMIC MEMORY (MEMORY MANAGEMENT)

Bahasa C membagi memori menjadi beberapa bagian, yaitu

  1. Code (Text), bagian ini berisi kode-kode mesin dari program yang sudah dikompilasi dan merupakan bagian yang hanya dapat dibaca (read only) untuk menghindari perubahan program yang tidak disengaja.
  2. Static (Globals), bagian ini dibagi menjadi dua, yaitu
    • Initialised data segment, bagian yang berisi semua variabel global, static, konstanta dan eksternal yang sudah diinisialisasi Bagian ini dibagi menjadi dua, yaitu bagian read only dan bagian read-write.
      #include <stdio.h>
      
      /* global variabel disimpan di initialised data segment  di bagian read-write */
      char c[] = "hello world";
      
      /* global variabel disimpan di initialised data segment  di bagian read-only */
      const char s[] = "learn to codes";
      
      int main() {
          /* variabel statis disimpan di initialised data segment */
          static int i = 10;
      
          return 0;
      }
      
    • Uninitialised data segment (.bss segment), bagian ini berisi semua variabel global, static dan eksternal yang belum diinisialisasi. Pada bagian ini, variabel global, static dan ekternal secara default diinisialisasi menjadi NOL sebelum program dieksekusi.
      #include <stdio.h>
      
      /* variabel yang belum diinisialisasi disimpan 
       * di uninitialized data segment (bss) 
       */
      char c;
      
      int main() {
          /* variabel statis yang belum diinisialisasi 
           * disimpan di uninitialized data segment (bss)
           */
          static int i;
      
          return 0;
      }
      
  1. Heap (Free Store), bagian yang digunakan untuk mengalokasikan memori secara dinamis. Bagian heap diatur oleh fungsi malloc(), calloc(), realloc() dan free() yang terdapat pada pustaka h.
  2. Stack, bagian yang digunakan untuk menyimpan semua variabel lokal dan digunakan untuk melewatkan argumen (parameter) ke fungsi dengan nilai balik (return value) dari instruksi yang dieksekusi setelah pemanggilan fungsi selesai. Semua pemanggilan fungsi dimasukkan ke dalam stack.

Memory Layout

Fokus penjelasan pada tutorial ini adalah bagian heap, yaitu mengalokasikan memori secara dinamis. Seperti yang sudah dijelaskan di atas, terdapat empat fungsi yang digunakan untuk mengatur bagian heap, yaitu

  1. malloc (memory allocation), digunakan untuk memesan sebuah blok memori dengan ukuran yang ditentukan dan mengembalikan sebuah pointer void berupa alamat memori blok memori pertama yang dialokasikan yang dapat diubah (cast) ke pointer bentuk lain.
  2. calloc (contiguous allocation), digunakan untuk memesan beberapa blok memori (multiple block memory) dengan ukuran yang sama untuk setiap blok memori dan menset semua byte pada setiap blok menjadi NOL.
  3. realloc (reallocate), digunakan untuk mengubah ukuran memori yang sudah dipesan sebelumnya.
  4. free, pengalokasian memori secara dinamis tidak dilepaskan (dibebaskan) secara otamatis. Program harus melepaskan (membebaskan) memori yang sudah tidak digunakan menggunakan fungsi free() agar tidak terjadi kebocoran memory (memory leak).

Berikut contoh penggunaan malloc() dan free().

#include <stdio.h>
#include <stdlib.h>

int main() {
    /* pointer ptr_i akan disimpan di stack */
    int *ptr_i;

    /* memesan memori pada bagian heap sebesar ukuran integer (4 byte) 
     * dan men-casting menjadi pointer bertipe integer
     */
    ptr_i = (int *) malloc(sizeof (int));

    *ptr_i = 10;

    printf("%d\n", *ptr_i);

    /* membebaskan memori yang sudah tidak digunakan lagi */
    free(ptr_i);

    return 0;
}

Asumsikan fungsi malloc() mengembalikan alamat memori 3A1828 pada bagian heap, maka ilustrasi alokasi memori pada source code di atas dapat dilihat pada gambar di bawah.

Memory Allocation

Selanjutnya adalah contoh penggunaan calloc().

#include <stdio.h>
#include <stdlib.h>

int main() {
    /* pointer ptr_i dan variabel i akan disimpan di stack */
    int *ptr_i, i;

    /* memesan memori pada bagian heap sebanyak 4 blok dengan ukuran 
     * masing-masing blok adalah ukuran integer (4 byte) dan men-casting 
     * menjadi pointer bertipe integer
     */
    ptr_i = (int *) calloc(4, sizeof (int));

    for (i = 0; i < 4; ++i) {
        /* mengisi setiap blok memori yang dipesan dengan nilai i */
        ptr_i[i] = i;
    }

    for (i = 0; i < 4; ++i) {
        printf("%d ", ptr_i[i]);
    }

    /* membebaskan memori yang sudah tidak digunakan lagi */
    free(ptr_i);

    return 0;
}

Memory Allocation 2

 

Fungsi malloc() juga dapat digunakan untuk memesan beberapa blok memori seperti fungsi calloc() dengan menggunakan cara sebagai berikut.

int *ptr_i;

ptr_i = (int *) malloc(sizeof(int) * 4);

Dengan mengalikan ukuran integer dengan empat, maka akan menghasilkan 4 blok memori seperti yang dihasilkan fungsi calloc().

Jadi apa yang menbedakan fungsi malloc() dan calloc()?

Fungsi calloc() menset setiap byte pada setiap blok memori yang dipesan menjadi NOL sedangkan fungsi malloc() tidak. Karena fungsi malloc() tidak menset setiap byte pada setiap blok memori yang dipesan, maka setiap block memori yang dipesan isinya adalah undefined (tidak diketahui/sembarang). Untuk lebih jelasnya perhatikan contoh di bawah.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr_i, *ptr_j, i, j;

    ptr_i = (int *) calloc(4, sizeof (int));
    ptr_j = (int *) malloc(sizeof (int) * 4);

    for (i = 0; i < 4; ++i) {
        printf("%d ", ptr_i[i]);
    }

    printf("\n");

    for (i = 0; i < 4; ++i) {
        printf("%d ", ptr_j[i]);
    }

    printf("\n");

    free(ptr_i);
    free(ptr_j);

    return 0;
}

calloc vs malloc

 

Contoh berikutnya adalah penggunaan fungsi realloc().

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr_i, i, n;

    printf("Masukkan ukuran array yang diinginkan: ");
    scanf("%d", &n);

    ptr_i = (int *) malloc(sizeof (int) * n);

    printf("Alamat memori yang dipesan\n");

    for (i = 0; i < n; ++i) {
        printf("%p\n", &ptr_i[i]);
    }

    printf("\n");

    printf("Masukkan ukuran BARU array yang diinginkan: ");
    scanf("%d", &n);

    ptr_i = realloc(ptr_i, n);

    printf("Alamat memori BARU yang dipesan\n");

    for (i = 0; i < n; ++i) {
        printf("%p\n", &ptr_i[i]);
    }

    return 0;
}

realloc 1realloc 2

3 comments

Leave a comment