Compiler C seperti gcc dan clang menerjemahkan pesan galat dalam format yang konsisten: nama file, nomor baris, nomor kolom, tingkat keparahan (error atau warning), dan deskripsi singkat. Membaca format pesan tersebut dengan cepat adalah keterampilan dasar yang mempercepat debugging. Pada chapter ini kita akan membedah struktur pesan error gcc, mengenali beberapa kategori error paling umum (sintaks, deklarasi, tipe, dan linker), dan melihat cara compiler memberi saran perbaikan melalui caret ^ dan note: tambahan.
Anatomi Pesan Error gcc #
Setiap pesan galat gcc selalu mengikuti pola yang sama. Kita dapat memecahnya menjadi empat komponen utama: lokasi (file:baris:kolom), tingkat keparahan (error/warning/note), deskripsi, dan blok konteks dengan caret ^ yang menunjuk titik persis galat ditemukan. Memahami urutan keempat komponen tersebut membuat kita tidak perlu membaca seluruh pesan untuk tahu mana yang fatal.
# File sumber: /tmp/test_err1.c
gcc -std=c11 -Wall -Wextra /tmp/test_err1.c -o /tmp/test_err1Sebelum menulis perintah compile di atas, mari kita lihat isi file /tmp/test_err1.c:
#include <stdio.h>
int main(void) {
printf("halo dunia\n")
return 0;
}Output yang Dihasilkan:
/tmp/test_err1.c: In function 'main':
/tmp/test_err1.c:3:27: error: expected ';' before 'return'
3 | printf("halo dunia\n")
| ^
| ;
4 | return 0;
| ~~~~~~Mari kita telaah baris-baris pesan di atas:
- Baris 1 (
/tmp/test_err1.c: In function 'main':): gcc menyatakan konteks fungsi tempat galat ditemukan. Pesan ini membantu kita melompat langsung ke fungsi terkait bila file berisi banyak fungsi. - Baris 2 (
/tmp/test_err1.c:3:27: error: ...): tripletfile:baris:kolommenandai titik galat. Baris ke-3 kolom ke-27 adalah posisi tepat setelah tanda kurung tutupprintf. Kata kuncierrorberarti kompilasi gagal. - Baris 3-6 (
3 | printf("halo dunia\n") ...): gcc mencetak ulang baris sumber dengan prefix nomor baris, lalu menambahkan caret^pada kolom 27. Setelah caret, gcc memberi saran;— tanda titik koma yang seharusnya hadir. - Baris 7-8 (
4 | return 0;): baris berikutnya juga dicetak ulang sebagai konteks agar kita melihat tokenreturnyang dipakai sebagai “anchor” saran perbaikan.
Kategori Error Umum #
Error Sintaks (Syntax Error) #
Syntax error adalah galat struktural: token yang hilang, urutan token salah, atau kurung tidak seimbang. Compiler mendeteksi syntax error saat parsing. Contoh paling sering adalah titik koma yang tertinggal, kurung kurawal yang tidak ditutup, dan koma yang kurang.
/* File: /tmp/test_err8.c */
#include <stdio.h>
int main(void) {
if (1) {
printf("ya\n");
return 0;
}Output yang Dihasilkan:
/tmp/test_err8.c: In function 'main':
/tmp/test_err8.c:6:1: error: expected declaration or statement at end of input
6 | }
| ^Pesan expected declaration or statement at end of input adalah ciri khas kurung kurawal yang tidak ditutup. gcc mencapai akhir file saat masih dalam keadaan “menunggu” penutup blok.
Error Deklarasi (Undeclared Identifier) #
Setiap identifier (variabel, fungsi, tipe) harus dideklarasikan sebelum dipakai. Bila tidak, gcc memunculkan error undeclared.
/* File: /tmp/test_err2.c */
#include <stdio.h>
int main(void) {
total = 10 + 20;
printf("total = %d\n", total);
return 0;
}Output yang Dihasilkan:
/tmp/test_err2.c: In function 'main':
/tmp/test_err2.c:3:5: error: 'total' undeclared (first use in this function)
3 | total = 10 + 20;
| ^~~~~
/tmp/test_err2.c:3:5: note: each undeclared identifier is reported only once for each function it appears inBaris note: memberitahu bahwa gcc hanya akan melaporkan identifier yang sama sekali tidak dikenal satu kali per fungsi, walau dipakai berkali-kali. Hal ini mencegah layar dipenuhi pesan duplikat yang sebenarnya berakar pada satu deklarasi yang tertinggal.
Implicit Function Declaration #
Bila kita memakai fungsi tanpa #include header yang menyatakannya (misalnya sqrt tanpa <math.h>), gcc mengeluarkan error -Wimplicit-function-declaration yang sejak C99 menjadi error secara default.
/* File: /tmp/test_err6.c */
int main(void) {
double r = sqrt(2.0);
return 0;
}Output yang Dihasilkan:
/tmp/test_err6.c: In function 'main':
/tmp/test_err6.c:2:16: error: implicit declaration of function 'sqrt' [-Wimplicit-function-declaration]
2 | double r = sqrt(2.0);
| ^~~~
/tmp/test_err6.c:1:1: note: include '<math.h>' or provide a declaration of 'sqrt'
+++ |+#include <math.h>
1 | int main(void) {gcc tidak hanya memberitahu file header yang hilang, tetapi juga mencetak saran #include <math.h> sebagai diff patch (+++ |+#include <math.h>).
Linker Error vs Compiler Error #
Compiler error muncul saat kompilasi (gcc -c), sedangkan linker error muncul saat tahap linking—setelah semua file .o berhasil dibuat. Linker error selalu diawali dengan /usr/bin/ld: dan biasanya berupa undefined reference to ....
/* File: /tmp/test_err7.c */
int main(void) {
extern int tidak_ada_func();
return tidak_ada_func();
}Output yang Dihasilkan:
/usr/bin/ld: /tmp/cc4yDC6t.o: in function `main':
test_err7.c:(.text+0xa): undefined reference to `tidak_ada_func'
collect2: error: ld returned 1 exit statusMari kita bedah elemen kunci pada output linker di atas:
/usr/bin/ld:: prefix menandakan pesan berasal dari linkerld, bukan compiler front-end. Hal ini menandakan tahap kompilasi sudah berhasil; masalah hanya pada resolusi simbol antar file.test_err7.c:(.text+0xa): section.textdi-offset0xa(10 byte) adalah lokasi instruksi pemanggilantidak_ada_func. Offset ini berguna bila kita memakaiobjdump -duntuk melihat instruksi assembly yang gagal.undefined reference to 'tidak_ada_func': simboltidak_ada_funcdijanjikan olehexterntetapi tidak didefinisikan di file mana pun yang di-link.collect2: error: ld returned 1 exit status:collect2adalah wrapper gcc yang memanggilld. Status keluar 1 menandakan kegagalan linking.
Strategi Membaca Pesan Bertumpuk #
Saat compiler mengeluarkan puluhan pesan sekaligus, perbaiki pesan paling atas lebih dulu. Banyak error di bawahnya sering kali adalah efek domino dari satu kesalahan awal—misalnya titik koma yang tertinggal membuat parser kehilangan anchor dan salah menafsirkan baris-baris setelahnya. Setelah perbaikan pertama diaplikasikan, compile ulang dan lihat apakah pesan berikutnya masih relevan.