Build yang sukses belum berarti program benar: hasil hitungannya bisa salah, atau program berjalan sebentar lalu mati tanpa pesan. Linux menyediakan peralatan pengamatan berlapis untuk momen-momen itu — dari printf yang sederhana sampai gdb yang menghentikan program di baris tertentu dan membedah memorinya. Tiga alat utama untuk aplikasi native — gdb, strace, dan ltrace — tidak terpasang di sistem latihan ini, jadi sesinya kita lihat lewat contoh tampilan; namun semua program latihan pada chapter ini dikompilasi dan dijalankan sungguhan, sehingga pola berpikirnya bisa diulang langsung.
Disiplin printf Debugging #
Teknik debugging tertua tetap yang tercepat untuk banyak kasus: cetak nilai variabel di titik-titik yang dicurigai. Kita pakai program penghitung faktorial yang jawabannya salah:
cat > faktorial.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
int hasil = 1;
for (int i = 1; i < 5; i++)
hasil = hasil * i;
printf("5! = %d\n", hasil);
return 0;
}
AKHIR
gcc -Wall -g -o faktorial faktorial.c
./faktorialOutput yang Dihasilkan:
5! = 24Program dikompilasi bersih tanpa warning, berjalan tanpa crash — dan mencetak 5! = 24, padahal 5! adalah 120. Bug semacam ini tidak tertangkap compiler karena sintaksnya sah; hanya hasil akhirnya yang bohong. Kita tambahkan jejak di dalam loop:
cat > faktorial.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
int hasil = 1;
for (int i = 1; i < 5; i++) {
hasil = hasil * i;
printf("i=%d hasil=%d\n", i, hasil);
}
printf("5! = %d\n", hasil);
return 0;
}
AKHIR
gcc -Wall -g -o faktorial faktorial.c
./faktorialOutput yang Dihasilkan:
i=1 hasil=1
i=2 hasil=2
i=3 hasil=6
i=4 hasil=24
5! = 24Jejaknya langsung membongkar masalah: iterasi terakhir mencetak i=4, artinya angka 5 tidak pernah dikalikan. Pandangan jatuh ke kondisi loop i < 5 — seharusnya i <= 5. Perbaikannya satu karakter, lalu kita jalankan ulang programnya:
cat > faktorial.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
int hasil = 1;
for (int i = 1; i <= 5; i++)
hasil = hasil * i;
printf("5! = %d\n", hasil);
return 0;
}
AKHIR
gcc -Wall -g -o faktorial faktorial.c
./faktorialOutput yang Dihasilkan:
5! = 120Alur kerjanya yang penting diingat: dugaan → jejak → bukti → perbaikan. printf menunjukkan apa yang terjadi, bukan mengapa — dan pada program yang besar atau berjalan cepat, mencetak segalanya menjadi tidak praktis. Di situlah kita naik kelas ke debugger sesungguhnya.
Program Jatuh: Exit Code 139 dan Sinyal #
Kelas bug kedua lebih dramatis: program mati seketika. Kita buat yang klasik — menulis ke pointer NULL:
cat > jatuh.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
int *penunjuk = 0;
printf("siap jatuh\n");
*penunjuk = 42;
return 0;
}
AKHIR
gcc -Wall -g -o jatuh jatuh.c
./jatuh
echo "exit code: $?"Output yang Dihasilkan:
exit code: 139Baris siap jatuh tercetak, lalu program berhenti di penulisan *penunjuk = 42 — kernel menolak tulisan ke alamat 0. Angka 139 adalah pesan sang kernel dalam bahasa exit code dari chapter Exit Codes
: nilai 128 ditambah 11, nomor sinyal SIGSEGV. Shell ikut menampilkan diagnostiknya (Segmentation fault) di layar, tetapi pesan itu dikirim ke stderr — yang tercatat sebagai stdout hanya baris exit code. Sebelum menyerah pada satu angka, echo $? cara tercepat menggolongkan kegagalan: 139 segfault, 134 abort, 137 dibunuh — semuanya sinyal, semuanya petunjuk arah.
gdb: Berhenti di Titik yang Dicurigai #
Debugger gdb menjalankan program di bawah kendali kita: berhenti di baris mana pun (breakpoint), periksa variabel, lanjut per baris atau per fungsi. Pasang dengan sudo apt install gdb lalu jalankan gdb ./faktorial. Sebagai contoh tampilan, inilah sesi tipikal memburu bug faktorial — breakpoint dipasang di baris printf terakhir:
(gdb) break faktorial.c:8
Breakpoint 1 at 0x1189: file faktorial.c, line 8.
(gdb) run
Starting program: /home/budi/faktorial
Breakpoint 1, main () at faktorial.c:8
8 printf("5! = %d\n", hasil);
(gdb) print hasil
$1 = 24Program berhenti tepat sebelum mencetak, dan print hasil memastikan nilainya sudah salah sebesar 24 — bukti kuat bugnya ada di dalam loop. Perintah sehari-hari hanya segelintir: break, run, next (melangkah per baris), print, dan backtrace yang mencetak tumpukan pemanggil — peta berharga saat crash terjadi jauh di dalam pustaka orang lain. Rinciannya di gdb(1)
.
Saat program yang crash membawa informasi berharga, core dump menyimpannya: kernel menuliskan memori proses ke file core di direktori kerja (diaktifkan dengan ulimit -c unlimited). Keesokan harinya bug bisa dibedah dengan gdb ./jatuh core — jalankan backtrace, dan baris yang melakukan penulisan haram ikut terbaca. Server produksi biasanya mematikan fitur ini dan mengarahkannya ke lokasi khusus lewat /proc/sys/kernel/core_pattern.
strace: Merekam Percakapan dengan Kernel #
Aplikasi tidak menyentuh perangkat keras secara langsung — setiap akses file, jaringan, dan memori melewati syscall, pintu resmi ke kernel yang kita kenal di chapter Process Concepts
. strace memasang perekam di pintu itu. Pasang dengan sudo apt install strace; sebagai contoh tampilan, ini rekaman strace ./halo pada program sapaan chapter sebelumnya:
execve("./halo", ["./halo"], 0x7ffc0099e370 /* 65 vars */) = 0
...
write(1, "Halo dari build otomatis!\n", 26) = 26
exit_group(0) = ?
+++ exited with 0 +++Empat baris itu menceritakan kehidupan singkat program: execve memuat binary, write menulis 26 byte ke stdout, dan exit_group(0) menutup proses dengan sukses — baris ... menandai syscall pemetaan memori dan perpustakaan yang diringkas agar contoh tetap pendek. Kekuatan strace terasa saat ada yang tidak masuk akal: program mengaku file tidak ada padahal ada (lihat path yang sebenarnya dibuka openat), atau aplikasi menggantung (syscall jaringan mana yang menunggu balasan). Opsi -c merangkum waktu tiap syscall — pemetaan awal yang bagus untuk kasus lambat. Rinciannya di strace(1)
.
ltrace dan Memilih Alat #
Kalau strace merekam percakapan program dengan kernel, ltrace merekam percakapannya dengan pustaka — malloc, strlen, SSL_read — dari pustaka dinamis yang dimuat lewat mekanisme linking chapter pkg-config dan Linking
. Dokumentasinya di ltrace(1)
. Peralatan kini lengkap, tinggal memilih sesuai gejala:
| Gejala | Alat pertama |
|---|---|
| Hasil hitungan salah | printf/logging di titik curiga |
| Perlu nilai variabel dan alur internal | gdb dengan breakpoint |
| Crash tanpa pesan | exit code, core dump, gdb backtrace |
| File “tidak ada” padahal ada / hang I/O | strace |
| Curiga pustaka lambat atau salah panggil | ltrace, strace -c |
Dengan toolchain yang sehat, environment yang terisolasi, dan peralatan debugging di tangan, ruang kerja development Linux kita lengkap. Perjalanan Course ini bergerak ke medan berikutnya: membawa Linux dari meja kerja ke server sungguhan. Pembukaannya ada di section Server Administration .