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!
