GDB-nin sadə kod üzərində istifadə nümunəsi
Debugger-lərdən Linux üzərində geniş istifadə olunan GDB ilə sadə bir kod səhvinin araşdırılmasına baxacıq.
Sadə kod nümunəmiz (“Expert MySQL” kitabının 162-ci səhifəsində “Listing 5-5”):
#include <stdio.h> #include <stdlib.h> static int factorial(int num) { int i; int fact = num; for(i = 1; i < num; i++){ fact += fact * i; } return fact; } int main(int argc, char *argv[]){ int num; int fact = 0; num = atoi(argv[1]); fact = factorial(num); printf("%d! = %d\n", num, fact); return 0; }
Compile edək və daha sonra run edək:
sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ gcc -g -o sample sample.c sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ ./sample Segmentation fault (core dumped)
İlk baxışdan heçnə aydın olmasa da, debug etdikdə bu segfault-un səbəbi aydın olur:
sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ gdb sample GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> Reading symbols from sample...done. (gdb) run Starting program: /home/sh/MySQLPakcages/Testing_Debuggers/sample Program received signal SIGSEGV, Segmentation fault. __GI_____strtol_l_internal (nptr=0x0, endptr=endptr@entry=0x0, base=base@entry=10, group=group@entry=0, loc=0x7ffff7dd2420 <_nl_global_locale>) at ../stdlib/strtol_l.c:293 293 ../stdlib/strtol_l.c: No such file or directory.
Backtrace-ə diqqət yetirək:
(gdb) bt #0 __GI_____strtol_l_internal (nptr=0x0, endptr=endptr@entry=0x0, base=base@entry=10, group=group@entry=0, loc=0x7ffff7dd2420 <_nl_global_locale>) at ../stdlib/strtol_l.c:293 #1 0x00007ffff7a493c2 in __strtol (nptr=<optimized out>, endptr=endptr@entry=0x0, base=base@entry=10) at ../stdlib/strtol.c:106 #2 0x00007ffff7a44e80 in atoi (nptr=<optimized out>) at atoi.c:27 #3 0x00000000004005c0 in main (argc=1, argv=0x7fffffffde18) at sample.c:19
Aydın olur ki, main-dən atoi funksiyası NULL pointer-lə çağrılıb və nəticə göz qabağındadır.
Məsələnin həlli üçün sadə check qoymaq kifayət edər:
#include <stdio.h> #include <stdlib.h> static int factorial(int num) { int i; int fact = num; for(i = 1; i < num; i++){ fact = fact * i; } return fact; } int main(int argc, char *argv[]){ int num; int fact = 0; if(argv[1] != NULL){ num = atoi(argv[1]); fact = factorial(num); printf("%d! = %d\n", num, fact); } else{ printf("No arguments were passed!\n"); } return 0; }
Fix-dən sonra yenidən çalışdıraq:
sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ !gcc gcc -g -o sample sample.c sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ ./sample No arguments were passed!