Home
Halaman Muka
|
|
|
|
Semua plug-ins di Netscape atau modul di Apache memakai teknik yang
sama, yaitu Dynamic Loading (DL). Ada beberapa terminologi lain untuk menyebutkan
teknik ini, seperti DSO (Dynamic Shared Object) atau DLL (Dynamic Link
Library). Tulisan ini akan memberikan pengantar tentang bagaimana membuat
program dengan memakai teknik ini.
1.Pendahuluan
Dalam pembuatan sebuah program, terkadang
kita tidak ingin semua fungsi diimplementasikan langsung pada program utama,
karena kita mungkin belum tahu fungsi apa saja yang harus disediakan. Atau
kita menginginkan pemakai program ini harus mempunyai kemungkinan untuk
menambahkan fungsi-fungsi yang belum ada pada program yang akan kita tulis.
Tentu saja semua itu harus dapat dilakukan tanpa harus melakukan proses
rekompilasi program utama dari awal. Teknik Dynamic Loading adalah solusi
yang tepat untuk merealisasikan keinginan di atas. Yang harus kita kerjakan
hanyalah menulis program pokok yang mempunyai kemampuan memuatkan (loading)
fungsi tambahan dan menginterpretasikan fungsi ini dengan benar. Sebelum
kita membahas lebih jauh, kita harus mengetahui terlebih dahulu bagaimana
tahapan proses dari file source code menjadi file yang bisa dieksekusi.
Kita akan memulai dengan menulis program yang sudah tidak asing lagi bagi
para pemrogram bahasa C yaitu Hello World.
#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello World");
}
Untuk melakukan proses kompilasi dapat dipakai perintah:
$ gcc -o hello hello.c
Instruksi di atas akan melakukan proses berikut:
1.Proses kompilasi
Source code hello.c dikompilasi menghasilkan file objek hello.o. Karena
fungsi printf() tidak diimplementasikan di file ini, maka kompiler akan
memberi catatan di tabel file objek ini bahwa fungsi printf() belum mempunyai
referensi.
2.Proses linking
Linker akan mencari di librari standard pengimplementasi fungsi yang
tidak dapat ditemukan pada saat proses kompilasi, dalam hal ini pengimplementasi
fungsi printf().
Perintah di atas secara implisit memanggil
linker dan menambahkan beberapa librari standar sebagai parameter. Di sini
pengimplementasi fungsi dari printf() akan ditemukan di libc yang juga
ditambahkan tanpa sepengetahuan sang pemrogram. Proses linking librari
ke program utama dibedakan menjadi dua tergantung dari caranya:
2.Proses linking statis (static linking).
Di sini jika pengimplementasi fungsi printf() ditemukan, maka akan
dikopikan ke dalam file objek hello.
3.Proses linking dinamis (dynamic linking).
Di sini libc diimplementasikan sebagai shared library. Linker hanya akan
mencatatkan referensi ke simbol pengimplementasi fungsi printf() pada file
objek hello.
Jika file program hello hasil dari proses
linking statis dieksekusi, maka objek file program akan dimuatkan ke memori.
Kemudian fungsi pertama, yang nama simbolnya tergantung dari sistem (contohnya
__main), akan dipanggil. Fungsi ini, yang biasanya didefinisikan oleh kompiler
atau librari akan melakukan seting dan initialisasi internal dan akhirnya
akan memanggil fungsi utama main() yang didefinisikan oleh user. Pada cara
kedua, jika program hello dieksekusi, maka objek file ini mula-mula juga
akan dimuatkan ke memori. Kemudian linker dinamis (dynamic linker) akan
membaca catatan referensi yang ada di file program hello yang dihasilkan
oleh linker sebelumnya. Jika objek file shared library yang berisi pengimplementasi
fungsi yang dibutuhkan belum dimuatkan ke memori, maka linker dinamis akan
secara rekursif memuatkan objek file shared library ini ke memori. Rekursif
berarti, jika suatu file shared library mempunyai referensi ke file shared
library lainnya, maka objek file shared library yang lain ini juga akan
dimuatkan ke memori (jika belum dimuat) dan seterusnya. Selanjutnya semua
referensi yang merujuk ke simbol pengimplementasi fungsi akan diperbaharui
ke posisi simbol yang aktual. Ini disebabkan posisi simbol pengimplementasi
baru dapat ditentukan setelah objek file shared library dimuatkan ke memori
(runtime). Dan posisi ini selalu berubah-ubah, tergantung dari banyak hal,
seperti kapan objek file shared library ini dimuatkan ke memori, objek
file shared library apa saja yang sudah dimuatkan ke memori dan sebagainya.
Karena kita hanya akan membahas cara yang kedua, maka untuk selanjutnya
terminologi librari dimaksudkan untuk merujuk ke shared library.
1.Shared Library
Seperti disebutkan di atas, setiap kali objek
file librari dimuatkan ke memori tidak selalu mempunyai posisi yang sama.
Maka posisi simbol di dalam file libraripun mempunyai alamat yang selalu
berubah. Oleh karena itu untuk mereferensi sebuah simbol, dilakukan pengalamatan
berbasis zero, yaitu pengalamatan yang relatif terhadap posisi awal dari
file librari. Setelah alamat posisi awal dapat ditentukan, maka referensi
semua simbol di file librari dapat dihitung pada saat waktu eksekusi (runtime).
Pada Program Library HOWTO [#!Wheeler!#] disebutkan tiga jenis librari,
selain librari statis (static library) dan shared library masih ada dynamic
loaded library.
Dilihat dari arsitektur filenya, tidak ada
perbedaan antara shared library dan dynamic loaded library. Pembedaan ini
hanya dipandang dari sisi pemrogramnya saja. Pada shared library, proses
loading dari objek file librari terjadi saat program utama dimuatkan ke
memori (proses linking dinamis seperti diuraikan di atas). Sedang pada
dynamic loaded library, proses loading dari file librari dapat berlangsung
kapan saja selama program utama dijalankan. Proses linking ini juga sering
disebut dengan runtime linking. Kita akan menamakan teknik yang memanfaatkan
runtime linking ini dengan nama Dynamic Loading. Sebelum teknik ini dibahas,
ada baiknya kita mengetahui aturan pemberian nama pada sebuah shared library,
walaupun aturan ini tidak sepenuhnya berlaku pada dynamic loaded library.
Penggunaan terminologi shared library untuk
selanjutnya berlaku juga pada dynamic loaded library. Berbeda dengan jenis
librari statis, shared library mempunyai dua jenis nama, yaitu soname dan
real name. Soname terdiri dari awalan lib, nama dari librari, kata .so
diikuti tanda titik (".") dan nomor versi mayor, seperti contohnya libhello.so.1.
Real name adalah nama file librari sebenarnya yang disusun dari soname
ditambah tanda titik ("."), nomor minor, dan kalau ada diikuti tanda titik
(".") dan nomor release, seperti contohnya libhello.so.1.1 atau libhello.so.1.1.5.
Selain kedua jenis nama di atas, masih ditambahkan satu jenis nama lagi
yaitu linker name yang sama dengan soname tanpa nomor versi mayor, seperti
contohnya libhello.so. Program yang membutuhkan file shared library akan
melakukan referensi menggunakan jenis nama ini. Secara umum linker name
adalah link ke soname dan soname adalah link ke real name.
2.API dari Dynamic Loading
Kebanyakan sistem operasi menyediakan API
(Application Program Interface) untuk penggunaan teknik Dynamic Loading.
Sayangnya, nama-nama API ini belum ada standarnya, sehingga secara umum
setiap sistem operasi menggunakan nama API sendiri-sendiri. Di sini kita
akan menggunakan API dari sistem operasi Linux. Sebelum kita mulai dengan
contoh program, kita akan membahas terlebih dahulu fungsi-fungsi API yang
ditulis dalam bahasa program C. Deklarasi dari fungsi-fungsi ini terdapat
di file header <dlfcn.h>. void* dlopen(const char* filename, int flag);
Fungsi ini bertujuan untuk memuatkan objek file filename ke memori. Jika
pemanggilan fungsi berhasil atau file objek filename sudah ada di memori,
maka fungsi akan mengembalikan sebuah handle sebagai hasilnya. Pada prinsipnya
handle ini dapat dibayangkan sebagai referensi yang merujuk ke file objek
filename.
Namun demikian handle ini tidak boleh diinterpretasikan
sebagai apapun juga, tapi hanya boleh digunakan sebagai parameter waktu
pemanggilan fungsi lainnya seperti dlsym() atau dlclose(). Setiap kali
fungsi ini dipanggil dengan sukses, maka librari dl akan memanajemen jumlah
pemakai handle ini dengan cara menginkrementasi variabel. Parameter flag
menentukan bagaimana dlopen() menangani simbol yang ada di objek filename.
RTLD_LAZY dan RTLD_NOW dengan kombinasi RTLD_GLOBAL atau RTLD_LOCAL dapat
digunakan untuk parameter ini. Intinya, pada RTLD_LAZY relokasi objek shared
library baru dilakukan pada saat referensi di shared library untuk pertama
kalinya dipanggil. Sedang pada RTLD_NOW proses relokasi dari semua objek
shared library yang dibutuhkan dilakukan setelah objek filename dimuatkan
ke memori. Dengan RTLD_GLOBAL, maka simbol di file shared library yang
dimuatkan akan dapat dipakai oleh shared library lainnya. Kalau hal ini
tidak dikehendaki maka dapat dipakai nilai RTLD_LOCAL yang juga merupakan
nilai default. char* dlerror(void); Dengan fungsi ini, informasi tentang
sebab-sebab terjadinya kesalahan pada proses linking dinamis dapat diakses.
Pada terjadinya kesalahan, fungsi ini akan mengembalikan null-terminated
character string sebagai hasilnya.
Jika pada pemrosesan terakhir tidak terjadi
kesalahan maka nilai NULL akan dikembalikan sebagai hasilnya. void* dlsym(void*
handle, char* simbol); Setelah objek file filename dimuatkan ke memori,
maka simbol-simbol di dalamnya dapat diakses dengan menggunakan fungsi
dlsym(). Sebagai parameter pertama adalah handle yang merupakan hasil dari
pemanggilan fungsi dlopen(). Parameter kedua simbol adalah nama fungsi
atau nama variabel yang akan diakses. Jika simbol tidak ditemukan, maka
fungsi akan mengembalikan NULL sebagai hasilnya. Pada kasus simbol ditemukan,
maka sebuah pointer akan dikembalikan oleh fungsi ini sebagai hasilnya.
Tergantung dari jenis simbol, pointer ini dapat diinterpretasikan sebagai
pointer dari suatu fungsi atau variabel.
Ada hal yang perlu mendapat perhatian di sini,
jika fungsi mengembalikan nilai NULL. Di sini ada dua kemungkinan, yaitu
simbol tidak ditemukan seperti diuraikan di atas, atau simbol ditemukan,
tetapi mempunyai nilai NULL. Untuk mendapatkan informasi yang benar, dapat
dilakukan dengan cara memanggil fungsi dlerror(), setelah pemanggilan fungsi
ini. Jika fungsi dlerror() mengembalikan nilai bukan NULL, maka dapat dipastikan
bahwa simbol tidak ditemukan. void* dlclose(void* handle); Fungsi ini adalah
kebalikan dari fungsi dlopen(). Setiap kali fungsi ini dipanggil dengan
sukses, maka librari dl akan memanajemen jumlah pemakai handle ini dengan
cara mendekrementasi variabel. File objek yang direferensi oleh handle
baru akan dihapuskan (unload) dari memori, jika sudah tidak ada lagi yang
menggunakan handle ini (jumlahnya nol).
3.Contoh pemakaian Dynamic Loading
Cara pemakaian API dari Dynamic Loading akan
diperlihatkan di sini dengan menggunakan program demo yang sederhana. Source
code program terdiri dari dua file, yaitu main.c dan simple_dl.c (Lihat
list program: script-1 adalah main.c, script-2 adalah simple_dl.c dan script-3
adalah Makefile). File main.c adalah program utama yang mempunyai fungsi
main(). Sedangkan file simple_dl.c adalah file modul yang berisi simbol
variabel dan simbol pengimplementasi fungsi yang akan diakses dari fungsi
main() dengan menggunakan fasilitas API Dynamic Loading. Dua simbol didefinisikan
di dalam simple_dl.c. Yang pertama adalah simbol variabel yang didefinisikan
sebagai berikut: char* info_linux = "Info Linux!"; Nama simbol variabel
ini adalah info_linux yang merupakan pointer dari tipe data char. Pada
pointer ini juga secara langsung dialokasikan sejumlah memori yang berisikan
karakter string "Info Linux!". Simbol kedua adalah hello_world yang merupakan
simbol dari pengimplementasi fungsi hello_world(). Pada prinsipnya nama
simbol tidak selalu sama dengan nama pengimplementasi fungsi. Kita akan
membahas hal ini secara ringkas pada bagian akhir dari artikel ini pada
kasus penulisan program menggunakan C++. Simbol fungsi ini didefinisikan
sebagai berikut: void hello_world(void); Fungsi ini hanya akan menampilkan
kalimat "Hello world!" di layar monitor. Sebelum kita membahas kode di
file main.c, kita akan mencoba untuk mengkompilasi file simple_dl.c. Untuk
dapat menghasilkan shared library, pada proses kompilasi harus digunakan
parameter -fPIC. PIC adalah kepanjangan dari position independent code.
Dengan instruksi berikut:
$ gcc -fPIC -c simple_dl.c
akan dihasilkan file objek simple_dl.o. Untuk mendapatkan file shared
library simple_dl.so dari file objek ini dapat digunakan instruksi:
$ gcc -shared -o simple_dl.so simple_dl.o
Untuk lebih yakin lagi, bahwa kedua simbol
info_linux dan hello_world terdapat di file shared library simple_dl.o
dapat digunakan program nm. Program ini adalah salah satu tools terdapat
pada binutils yang dapat menampilkan simbol dari sebuah objek file. Instruksi
$ nm -g --defined-only -n simple_dl.so
hanya akan menampilkan simbol global yang sudah terdefinisi. Daftar
simbol akan ditampilkan secara berurutan menurut alamat relatif simbol,
seperti yang terlihat di bawah ini:
00000618 ? _init
000007a0 T hello_world
00000840 A _etext
00000840 ? _fini
00001880 D info_linux
00001898 A _GLOBAL_OFFSET_TABLE_
000018cc A _DYNAMIC
00001964 A __bss_start
00001964 A _edata
0000197c A _end
Kolom kedua di atas menunjukkan tipe dari
simbol. Huruf T mempunyai arti bahwa posisi simbol yang bersangkutan berada
di bagian kode atau text, seperti halnya pada simbol hello_world yang adalah
pengimplementasi fungsi. Sedangkan huruf D seperti pada simbol info_linux
menandakan bahwa posisi simbol yang bersangkutan berada di bagian data
yang terinitialisasi. Sekarang kita akan beralih membahas kode di dalam
file main.c. Di sini kita mendefinisikan beberapa variabel. Dua diantaranya
adalah void (*pFuncSimbol)(); dan char** pVarSimbol; Yang pertama adalah
variabel pointer dari fungsi yang tidak mempunyai parameter (void) dan
tidak mempunyai nilai kembali(void). Sedangkan variabel kedua adalah pointer
dari character string. Sekarang kita akan membahas fungsi-fungsi yang dipakai
di sini satu persatu.
handle = dlopen("./simple_dl.so", RTLD_NOW);
if (!handle) {
printf("Failed: %s\n", dlerror());
return 1;
}
Pertama-tama fungsi dlopen() akan dipanggil
untuk memuatkan objek file shared library simple_dl.so ke memori. Program
akan berakhir jika file ini tidak ditemukan. Jika objek file ini dapat
dimuatkan ke memori dengan sukses, maka variabel handle selanjutnya dapat
dipakai sebagai parameter untuk memanggil fungsi lainnya.
pFuncSimbol = (void (*)())dlsym(handle, "hello_world");
error = dlerror();
if (error) {
printf("Failed(2): %s\n", error);
return 1;
}
Fungsi dlsym() di atas dipanggil untuk mendapatkan
referensi dari simbol hello_world. Jika simbol ini tidak ditemukan maka
program akan berakhir. Informasi ini didapatkan dengan cara memanggil fungsi
dlerror() yang akan mengembalikan hasil bukan NULL(lihat di atas tentang
dlsym()). Jika simbol ditemukan, maka variabel pFuncSimbol sekarang mempunyai
referensi ke simbol hello_world dari shared library simple_dl.so.
pFuncSimbol();
Dengan instruksi di atas, maka fungsi yang
direferensi oleh variabel pFuncSimbol yang tak lain adalah fungsi hello_world
di simple_dl.so akan dipanggil. Hasilnya dapat dilihat di layar monitor,
yaitu penampilan character string "Hello world!".
pVarSimbol = (char**)dlsym(handle, "info_linux");
error = dlerror();
if (error) {
printf("Failed(2): %s\n", error);
return 1;
}
Seperti sebelumnya, di sini fungsi dlsym()
dipakai untuk mendapatkan referensi dari simbol info_linux. Jika simbol
ditemukan, maka sekarang pVarSimbol mempunyai referensi ke simbol info_linux
yang isinya tidak lain adalah character string "Info Linux!".
printf("%s\n", *pVarSimbol);
Di sini isi dari referensi pVarSimbol "Info
Linux!" akan ditampilkan di layar monitor.
dlclose(handle);
Setelah kita tidak membutuhkan lagi, maka
kita harus menutup handle yang telah kita buka sebelumnya. Untuk menghasilkan
file program main yang dapat dieksekusi, dapat digunakan instruksi seperti
berikut:
$ gcc -o main main.c -ldl
Dengan parameter -ldl maka pada proses linking
shared library libdl.so yang mengimplementasi API Dynamic Loading akan
ditambahkan. Setelah berhasil, jika program main dieksekusi maka di layar
monitor akan ada tampilan sebagai berikut:
$ ./main
Hello world!
Info Linux!
4.Memanggil Fungsi di Program Utama dari Objek shared library
Pada banyak kasus kita akan memerlukan fungsi
yang sudah diimplementasikan di program utama untuk dipanggil dari objek
shared library. Dari sisi objek shared library sendiri tidak ada masalah,
selama fungsi ini sudah terimplementasi di program utama, karena pembuatan
file shared library tidak membutuhkan proses linking. Yang menjadi kunci
pokok di sini adalah, bahwa simbol fungsi di program utama harus ditambahan
ke tabel simbol dinamik (dynamic symbol table). Tabel ini memuat semua
simbol yang akan dapat diakses oleh semua objek shared library pada saat
runtime. Hal ini dapat dilakukan dengan menambahkan parameter -rdynamic
pada proses pembuatan file program utama. Parameter ini akan menginstruksikan
kompiler untuk melewatkan parameter -export-dynamic pada proses linking
oleh ld. Jika parameter ini tidak ditambahkan, maka tabel simbol dinamik
hanya akan berisi simbol yang direferensi oleh objek shared library saat
proses linking pada pembuatan file program utama. Kita akan menambahkan
beberapa baris pada file main.c dan simple_dl.c untuk menunjukkan hal di
atas. Pada file main.c ditambahkan sebuah fungsi hello_main() yang akan
dipanggil dari file simple_dl.c.
/*==============================
* Fungi tambahan di file main.c
*/
void hello_main(const char* txt)
{
printf("%s\n", txt);
}
Fungsi hello_main() hanya akan menampilkan isi string txt yang dilewatkan
melalui parameter.
void hello_world(void)
{
printf("Hello world!\n");
/* ========================================
* Memanggil fungsi yang ada di file main.c
*/
hello_main("Saya simple_dl");
}
Fungsi hello_main() di program utama akan dipanggil setelah fungsi
helllo_world() ini dipanggil oleh program utama. Proses pembuatan objek
shared library simple_dl.so sama seperti diterangkan sebelumnya. Pada pembuatan
objek program utama, harus ditambahkan parameter -rdynamic seperti berikut:
$ gcc -rdynamic -o main main.c -ldl
Hasil dari pengeksekusian program main dapat
dilihat pada tampilan monitor:
$ ./main
Hello world!
Saya simple_dl
Info Linux!
5.Fungsi _init() dan _fini()
Fungsi _init() dan _fini() adalah dua fungsi
khusus pada sebuah file shared library. Fungsi _init() akan dipanggil oleh
librari dl setelah sebuah objek file shared library dimuatkan ke memori
dengan instruksi dlopen(). Sedang sebelum shared library dihapuskan(unload)
dari memori lewat instruksi dlclose(), librari dl akan memanggil fungsi
_fini(). Kita dapat memanfaatkan kedua fungsi ini dengan cara mengimplementasikan
kedua fungsi tersebut dalam shared library yang kita tulis. Pada umumnya
fungsi _init() digunakan untuk menginitialisasi variabel ataupun mengalokasi
memori. Fungsi _fini() sebaliknya dapat digunakan untuk menghapuskan memori
yang dialokasi sebelumnya. Untuk menghindari pengimplementasian ganda,
pada saat proses kompilasi pembuatan shared library harus ditambahkan parameter
-nostartfiles, seperti contohnya:
$ gcc -shared -nostartfiles -o simple_dl.so simple_dl.o
6.Penggunaan C++
Pada penggunaan bahasa C++ ada beberapa aspek
yang perlu mendapat perhatian. Salah satu hal yang membedakan antara C++
dan C adalah, bahwa di C++ kita dapat mempunyai beberapa fungsi dengan
nama yang sama tetapi parameter yang berbeda. Terminologi yang sering dipakai
untuk ini pada bahasa yang mendukung object oriented adalah overloading.
Lain dengan bahasa C, di sini nama fungsi saja tidak cukup untuk dijadikan
sebagai identitas yang unik (unique identifier) di tabel simbol. Untuk
mendapatkan identitas yang unik ini, akan dilakukan proses mangling terhadap
nama fungsi di C++ yang menyertakan informasi parameternya. Misalnya saja
dengan memakai gcc, simbol fungsi foobar dengan parameter tunggal int akan
berubah menjadi foobar__Fi. Proses mangling ini bergantung kepada jenis
kompiler, sehingga pada pemakaian kompiler yang berbeda akan dihasilkan
identitas unik yang berbeda juga. Dengan menggunakan program c++filt yang
juga terdapat dalam paket binutils, kita dapat melakukan proses demangling,
yaitu proses kebalikan dari mangling. Contohnya dengan intruksi
c++filt foobar__Fi
maka dari simbol foobar__Fi kita akan mendapatkan kembali nama fungsi
dengan parameternya foobar(int). Hal di atas akan membuat masalah pada
pembuatan program yang memakai bahasa C dan C++, karena simbol fungsi program
yang ditulis dengan C juga akan dilakukan proses mangling.
Sebagai contoh kita ingin menulis program
yang memakai librari dari pihak ketiga yang hanya memberikan file header
dan file objek shared library yang ditulis dengan bahasa C. Sedangkan program
yang kita tulis menggunakan bahasa C++ yang akan memanggil beberapa fungsi
di librari ini.
Pada proses kompilasi, simbol fungsi di file
header akan dilakukan proses mangling, sehingga pada proses linking akan
mengakibatkan kesalahan, karena simbol tidak dapat ditemukan. Untuk mencegahnya,
simbol fungsi pada file header tidak boleh dilakukan proses mangling oleh
kompiler. Ini dapat dilakukan dengan menambahkan deklarasi extern "C" di
file header yang akan membuat kompiler untuk memakai konvensi nama C (C
name convention). Karena pada kompiler C++ biasanya didefinisikan makro
__cplusplus maka penambahan header dapat dilakukan sbb:
#ifdef __cpluplus
extern "C" {
#endif
......
#ifdef __cpluplus
}
#endif
Jika librari dimuatkan menggunakan Dynamic
Loading dan fungsi di librari dipanggil dengan memakai fungsi dlsym(),
maka masalah di atas tidak akan terjadi, karena pada simbol fungsi di librari
tidak dilakukan proses mangling. Masalah lain yang timbul sehubungan dengan
pemakaian bahasa C++ adalah kita tidak dapat memakai fungsi dlsym() untuk
memanggil fungsi di librari yang ditulis memakai bahasa C++. Hal ini diakibatkan
karena pada semua simbol akan dilakukan proses mangling, sehingga kita
tidak akan tahu nama simbol dari fungsi yang kita inginkan.
7.Penutup
Penerapan teknik Dynamic Loading akan memudahkan
pengembangan suatu aplikasi besar yang dilakukan oleh sekelompok pemrogram
seperti halnya aplikasi web server Apache. Program utamanya hanya mengimplementasi
fungsi pokok saja, sedang fungsi-fungsi lainnya ditambahkan dalam bentuk
modul secara fleksibel bergantung dari keperluan. Salah satu faktor yang
tidak menguntungkan adalah lamanya waktu proses pemuatan file shared library
ke memori dan proses pereferensian dari simbol. Jika modul-modul dimuatkan
hanya pada saat awal saja, maka faktor di atas tidak terlalu penting. Aplikasi
bot irc eggdrop memakai teknik lain untuk menghindari faktor di atas. Pengaksesan
ke simbol dilakukan dengan melalui tabel yang berisikan pointer statis
dari simbol. Akhir kata, semoga artikel ini bermanfaat dan dapat menambah
wacana teknik pemrograman bagi pembaca.
Eko Bono Suprijadi
|