Ada sedikit cerita lagi dari pengalaman saya ketika berhadapan dengan galat atau error pemrograman bernama “segmentation fault“. Galat ini menurut pendapat saya pribadi adalah galat paling angker dalam pengalaman saya belajar pemrograman, khususnya bahasa C. Galat ini jadi angker karena ada beberapa penyebab yang memungkinkan ia timbul dan cukup sulit untuk dideteksi karena secara sintaks dan grammar program yang kita tulis sudah benar. Kompilasi dan linking sudah lewat dan berjalan tanpa error tapi ketika program dijalankan ia akan berhenti dan menampilkan pesan angker “segmentation fault”. Jika menggunakan cara biasa dengan memandangi kode program baris demi baris, dapat dipastikan penyelesaian galat ini akan butuh waktu yang cukup lama apalagi jika program yang sedang kita kembangkan cukup besar dan terdiri dari puluhan berkas.
Cara lain yang lebih baik untuk menganalisis dan menyelesaikan “segmentation fault” dan error lain pada umumnya tentu saja menggunakan debugger (sesuai judul postingan ini). Dengan menggunakan debugger kita dapat menemukan di bagian mana program mengalami error, mengawasi jalannya program, menjalankan program baris demi baris, memeriksa atau mengubah nilai variabel, membuat break points, dll. Sebagai contoh, berikut ini sebuah program kecil yang akan menampilkan pesan galat “segmentation fault”.
- Code:
-
#include
#include
int
main(int argc, char *argv[]) {
FILE *p1, *p2;
p1 = fopen("data", "r");
p2 = fopen("results", "w");
fclose(p1);
fclose(p2);
return 0;
}
If you’re a C progammer, even a newbie like me, you may notice the line that will cause the error :D but it’s okay for the purpose of this article, let’s just continue. Mari kita kompilasi dan jalankan program ini seperti biasa.
- Code:
-
gcc segfault.c
./a.out
Ooops, we got an error message.
[You must be registered and logged in to see this image.]It’s time to fire up our gdb to find out what the hell is going on in our little program. Tapi sebelumnya kita perlu kompilasi ulang program yang akan di-debug dengan opsi debugging, sebab tanpa opsi ini gdb tidak akan mampu menampilkan informasi yang kita butuhkan. Okay, let’s do this.
- Code:
-
ulimit -c unlimited
gcc -g segfault.c
Now we have to rerun our little program, and as expected we still got the same error message. Tapi kali ini kita juga dapat berkas core dump untuk dianalisis dengan gdb.
[You must be registered and logged in to see this image.] - Code:
-
gdb a.out core
You’ll see the welcome screen of gdb, like the picture below, then type run to execute our little program.
[You must be registered and logged in to see this image.]Coba perhatikan pesan-pesan error tersebut, mmm… kalau dilihat-lihat sepertinya masalahnya datang dari fclose tapi kalau dipikir-pikir lagi masalah ini tidak mungkin datang dari pustaka standar di mana fclose berada (karena kalau sampai itu terjadi, kita dalam MASALAH BESAR). If so, let’s check in our program. First let’s kill the running program, set a break points at the first appearance fclose (line 12th in the source code above), then run the program.
[You must be registered and logged in to see this image.]Itu dia, sekarang kita berhenti di baris ke-12 di fungsi fclose(p1), dengan membaca manual dari fclose kita tahu bahwa argumen p1 ini haruslah sebuar pointer bertipe FILE yang valid/legal jika tidak maka akan terjadi sesuatu yang tidak terduga. Okelah kalau begitu, kita periksa dulu nilai variable p1.
[You must be registered and logged in to see this image.]Dan ternyata oh ternyata, this is the root cause of our error. Terang saja ini illegal dan tidak diperbolehkan. Fine, we’ve found the problem and now what? Kalau dirunut-runut lagi, p1 itu datang dari fungi fopen dibaris 9, di bari itu kita memanggil fungsi fopen dengan opsi “r” untuk membaca berkas yang tidak ada. So, to solve this problem we have to pass a file that really exist to fopen or add an error trap to our code.
- Code:
-
p1 = fopen("data", "r");
if (p1 == NULL) {
fprintf(stderr, "Berkas itu tidak ada\n");
exit(1);
}
Coba compile lagi, trus dijalankan, seharusnya tidak ada galat lagi.
Referensi:
[You must be registered and logged in to see this link.]