GNU Debugger ή GDB: Ένα ισχυρό εργαλείο εντοπισμού σφαλμάτων πηγαίου κώδικα για προγράμματα Linux
Ο εντοπισμός σφαλμάτων παίζει ζωτικό ρόλο σε οποιοδήποτε σύστημα ανάπτυξης λογισμικού. Κανείς δεν μπορεί να γράψει έναν κώδικα χωρίς σφάλματα ταυτόχρονα. Κατά τη διάρκεια της ανάπτυξης, δημιουργούνται σφάλματα και πρέπει να επιλυθούν για περαιτέρω βελτίωση. Ένα σύστημα ανάπτυξης είναι ατελές χωρίς πρόγραμμα εντοπισμού σφαλμάτων. Λαμβάνοντας υπόψη την κοινότητα προγραμματιστών ανοιχτού κώδικα, το GNU Debugger είναι η καλύτερη επιλογή τους. Χρησιμοποιείται επίσης για εμπορική ανάπτυξη λογισμικού σε πλατφόρμες τύπου UNIX.
Το GNU Debugger, γνωστό και ως gdb, μας επιτρέπει να διερευνούμε κρυφά τον κώδικα ενώ εκτελείται ή τι προσπαθούσε να κάνει ένα πρόγραμμα τη στιγμή πριν διακοπεί. Το GDB βασικά μας βοηθά να κάνουμε τέσσερα κύρια πράγματα για να εντοπίσουμε ελαττώματα στον πηγαίο κώδικα.
- Ξεκινήστε το πρόγραμμα, προσδιορίζοντας ορίσματα που μπορεί να επηρεάσουν τη γενική συμπεριφορά.
- Σταματήστε το πρόγραμμα σε καθορισμένες συνθήκες.
- Εξετάστε τη συντριβή ή πότε διακόπηκε το πρόγραμμα.
- Αλλάξτε τον κώδικα και πειραματιστείτε με τον τροποποιημένο κώδικα αμέσως.
Μπορούμε να χρησιμοποιήσουμε το gdb για τον εντοπισμό σφαλμάτων προγραμμάτων γραμμένων σε C και C++ χωρίς μεγάλη προσπάθεια. Προς το παρόν, η υποστήριξη για άλλες γλώσσες προγραμματισμού όπως D, Modula-2, Fortran είναι μερική.
Ξεκινώντας με το GNU Debugger ή το GDB
Το GDB καλείται χρησιμοποιώντας την εντολή gdb. Κατά την έκδοση gdb, εμφανίζει ορισμένες πληροφορίες σχετικά με την πλατφόρμα και σας στέλνει στην προτροπή (gdb) όπως φαίνεται παρακάτω .
[root@fedora20 ~]# gdb
Δείγμα εξόδου
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb)
Πληκτρολογήστε help list για να δείτε τις διαφορετικές κατηγορίες εντολών που είναι διαθέσιμες στο gdb. Πληκτρολογήστε help ακολουθούμενη από ένα όνομα κλάσης για μια λίστα εντολών σε αυτήν την κλάση. Πληκτρολογήστε help all για τη λίστα όλων των εντολών. Οι συντομογραφίες ονομάτων εντολών επιτρέπονται εάν είναι σαφείς. Για παράδειγμα, μπορείτε να πληκτρολογήσετε n αντί να πληκτρολογήσετε next ή c για continue και ούτω καθεξής.
Οι πιο συχνά χρησιμοποιούμενες εντολές GDB
Οι εντολές gdb που χρησιμοποιούνται συνήθως παρατίθενται στον παρακάτω πίνακα. Αυτές οι εντολές πρόκειται να χρησιμοποιηθούν από τη γραμμή εντολών gdb (gdb).
-
Command
- Περιγραφή
-
run
- Ξεκινήστε μια εκτέλεση προγράμματος
-
quit
- Τερματισμός gdb
-
print expr
- Εκτύπωση έκφρασης όπου expr μπορεί να είναι επίσης όνομα μεταβλητής
-
next
- Μετάβαση στην επόμενη γραμμή
-
step
- Μεταβείτε στην επόμενη γραμμή
-
continue
- Συνεχίστε από την τρέχουσα γραμμή μέχρι το τέλος του προγράμματος ή το επόμενο σημείο διακοπής
Σημειώστε τη διαφορά μεταξύ των δύο εντολών βήμα και next. Η εντολή next δεν μπαίνει μέσα στη συνάρτηση εάν η επόμενη γραμμή είναι κλήση συνάρτησης. Ενώ η εντολή step μπορεί να μπει στην εσωτερική λειτουργία και να δει τι συμβαίνει εκεί.
Ένα δείγμα συνεδρίας με το GDB
Εξετάστε τον ακόλουθο πηγαίο κώδικα.
// sum.c
#include <stdio.h>
int sum (int a, int b) {
int c;
c = a + b;
return c;
}
int main() {
int x, y, z;
printf("\nEnter the first number: ");
scanf("%d", &x);
printf("Enter the second number: ");
scanf("%d", &y);
z = sum (x, y);
printf("The sum is %d\n\n", z);
return 0;
}
Για να εντοπίσουμε σφάλματα στο αρχείο εξόδου πρέπει να μεταγλωττίσουμε το ίδιο με την επιλογή -g σε gcc ως εξής.
gcc -g sum.c -o sum
Το αρχείο εξόδου sum μπορεί να επισυναφθεί στο gdb με έναν από τους παρακάτω 2 τρόπους:
1. Καθορίζοντας το αρχείο εξόδου ως όρισμα στο gdb.
gdb sum
2. Εκτέλεση αρχείου εξόδου μέσα στο gdb χρησιμοποιώντας την εντολή file.
gdb
(gdb) file sum
Η εντολή list παραθέτει γραμμές στο αρχείο πηγαίου κώδικα και μετακινεί τον δείκτη. Έτσι, η πρώτη listθα εμφανίσει τις πρώτες 10 γραμμές και η επόμενη list εμφανίζει τις επόμενες 10 και ούτω καθεξής.
(gdb) list
1 #include <stdio.h>
2
3 int sum (int a, int b) {
4 int c;
5 c = a + b;
6 return c;
7 }
8
9 int main() {
10 int x, y, z;
Για να ξεκινήσετε την εκτέλεση, εκδώστε την εντολή run. Τώρα το πρόγραμμα εκτελείται κανονικά. Αλλά ξεχάσαμε να βάλουμε κάποια σημεία διακοπής στον πηγαίο κώδικα για τον εντοπισμό σφαλμάτων, σωστά; Αυτά τα σημεία διακοπής μπορούν να καθοριστούν για συναρτήσεις ή σε καθορισμένες γραμμές.
(gdb) b main
Σημείωση: Έχω χρησιμοποιήσει μια συντομογραφία b για διάλειμμα.
Αφού ρυθμίσετε το σημείο διακοπής στην κύρια λειτουργία, η επανάληψη του προγράμματος θα σταματήσει στη γραμμή 11. Το ίδιο πράγμα μπορεί να εφαρμοστεί εάν ο αριθμός γραμμής είναι γνωστός από πριν.
(gdb) b sum.c:11
Τώρα περάστε μέσα από τις γραμμές κώδικα χρησιμοποιώντας την εντολή next ή n. Είναι σημαντικό να σημειωθεί ότι η εντολή next δεν μπαίνει στον κώδικα συνάρτησης εκτός εάν οριστεί ένα σημείο διακοπής στη συνάρτηση. Ας δοκιμάσουμε τώρα την εντολή print. Ορίστε το σημείο διακοπής στο άθροισμα συνάρτησης όπως παρακάτω.
(gdb) b sum
Breakpoint 1 at 0x4005aa: file sum.c, line 5.
(gdb) r
Starting program: /root/sum
Enter the first number: 2
Enter the second number: 3
Breakpoint 1, sum (a=2, b=3) at sum.c:5
5 c = a + b;
(gdb) p a
$1 = 2
(gdb) p b
$2 = 3
(gdb) c
Continuing.
The sum is 5
[Inferior 1 (process 3444) exited normally]
Εάν το πρόγραμμα που εκτελείται απαιτεί παραμέτρους γραμμής εντολών, τότε δώστε τις ίδιες μαζί με την εντολή run ως.
(gdb) run . . .
Τα αρχεία κοινόχρηστης βιβλιοθήκης που σχετίζονται με το τρέχον πρόγραμμα που εκτελείται μπορούν να παρατίθενται ως.
(gdb) info share
From To Syms Read Shared Object Library
0x00000035a6000b10 0x00000035a6019c70 Yes /lib64/ld-linux-x86-64.so.2
0x00000035a641f560 0x00000035a6560bb4 Yes /lib64/libc.so.6
Τροποποίηση μεταβλητών
Το GDB είναι επίσης ικανό να τροποποιεί μεταβλητές σε όλη την εκτέλεση του προγράμματος. Ας το δοκιμάσουμε αυτό. Όπως αναφέρθηκε παραπάνω, ορίστε το σημείο διακοπής στη γραμμή 16 και εκτελέστε το πρόγραμμα.
(gdb) r
Starting program: /root/sum
Enter the first number: 1
Enter the second number: 2
Breakpoint 1, main ( ) at sum.c:16
16 printf("The sum is %d\n\n", z);
(gdb) set z=4
(gdb) c
Continuing.
The sum is 4
Τώρα a=1, b=2 και το αποτέλεσμα θα πρέπει να είναι z=3. Αλλά εδώ αλλάξαμε το τελικό αποτέλεσμα σε z=4 στην κύρια συνάρτηση. Με αυτόν τον τρόπο ο εντοπισμός σφαλμάτων μπορεί να γίνει ευκολότερος χρησιμοποιώντας το gdb.
Ενεργοποίηση/απενεργοποίηση σημείων διακοπής
Για να λάβετε τη λίστα με όλα τα σημεία διακοπής, πληκτρολογήστε σημεία διακοπής πληροφοριών.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004005c2 in main at sum.c:11
Εδώ υπάρχει μόνο ένα σημείο διακοπής και είναι το To. enabled disable the breakpoints καθορίζουν τον αριθμό του σημείου διακοπής μαζί με την εντολή disable. Για να ενεργοποιήσετε στη συνέχεια χρησιμοποιήστε την εντολή enable.
(gdb) disable 1
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep n 0x00000000004005c2 in main at sum.c:11
Μπορείτε επίσης να διαγράψετε τα σημεία διακοπής με την εντολή delete.
Εντοπισμός σφαλμάτων εκτελούμενων διεργασιών
Πολλές διεργασίες εκτελούνται στο παρασκήνιο σε ένα σύστημα GNU/Linux. Για τον εντοπισμό σφαλμάτων μιας διεργασίας που εκτελείται πρώτα από όλα πρέπει να βρούμε το αναγνωριστικό διεργασίας της συγκεκριμένης διεργασίας. Η εντολή pidof σας δίνει το pid μιας διαδικασίας.
pidof <process_name>
Τώρα πρέπει να επισυνάψουμε αυτό το pid στο gdb. Υπάρχουν 2 τρόποι.
1. Καθορίζοντας το pid μαζί με το gdb.
gdb -p <pid>
2. Χρησιμοποιώντας την εντολή attach από το gdb.
(gdb) attach <pid>
Αυτα για τωρα. Αυτά είναι μόνο τα βασικά του gdb για να κάνετε μια καλή αρχή στον εντοπισμό σφαλμάτων του πηγαίου κώδικα και είναι πολύ περισσότερα από τα πράγματα που εξηγήθηκαν παραπάνω. Για παράδειγμα, μπορούμε να εντοπίσουμε σφάλματα χρησιμοποιώντας τις πληροφορίες στοίβας, τις μεταβλητές περιβάλλοντος και πολλά άλλα. Προσπαθήστε να παίξετε με όλα αυτά τα πράγματα…