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!
Səs: +30. Bəyənilsin Zəifdir

Müəllif: Şəhriyar Rzayev

Şərh yazın