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”):

---------------------- KOD ----------------------
#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:

---------------------- KOD ----------------------
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:

---------------------- KOD ----------------------
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:

---------------------- KOD ----------------------
(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:

---------------------- KOD ----------------------
#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:

---------------------- KOD ----------------------
sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ !gcc
gcc -g -o sample sample.c
sh@sh-ubuntu:~/MySQLPakcages/Testing_Debuggers$ ./sample
No arguments were passed!
Səs: +30. Bəyənilsin Zəifdir

Müəllif: Şəhriyar Rzayev

Şərh yazın