Σφάλμα: 'Το GDB δεν έχει πρόσβαση στη μνήμη στη διεύθυνση' σε C++

Sphalma To Gdb Den Echei Prosbase Ste Mneme Ste Dieuthynse Se C



Ο εντοπισμός σφαλμάτων είναι ένα ουσιαστικό μέρος της διαδικασίας κατά την ανάπτυξη εφαρμογών σε C++ ή σε οποιαδήποτε άλλη γλώσσα προγραμματισμού. Η δημιουργία εφαρμογών σε C++ δεν είναι εύκολη. περιλαμβάνει καλές δεξιότητες δομής δεδομένων, δεξιότητες διόρθωσης σφαλμάτων και διαχείριση των εργαλείων εντοπισμού σφαλμάτων. Το GDB, GNU Debugger, είναι ένα αποτελεσματικό εργαλείο που βοηθά τους προγραμματιστές να εντοπίσουν και να επιλύσουν τα σφάλματα στον κώδικά τους. Το GDB είναι ένα ενδιαφέροντα απλό και χρήσιμο εργαλείο που βοηθά τους προγραμματιστές να βρουν και να διορθώσουν τα σφάλματα κώδικα.

Ωστόσο, κατά τη χρήση του GDB, ενδέχεται να αντιμετωπίσετε το σφάλμα 'σφάλμα: Το GDB δεν έχει πρόσβαση στη μνήμη στη διεύθυνση'. Αυτό το σφάλμα μπορεί να προκαλέσει σύγχυση και δυσκολεύει τη συνέχιση του εντοπισμού σφαλμάτων. Αυτό το άρθρο επικεντρώνεται στον εντοπισμό γιατί παρουσιάζεται αυτό το σφάλμα και στην εξέταση ορισμένων παραδειγμάτων κώδικα που μας βοηθούν να κατανοήσουμε πώς να επιλύσουμε αυτό το σφάλμα.

Παράδειγμα 1:

Ας δούμε το πρώτο μας παράδειγμα κώδικα που, κατά την εκτέλεση, δίνει ένα σφάλμα 'Το GDB δεν έχει πρόσβαση στη μνήμη στη διεύθυνση'. Αρχικά, εξετάζουμε τον κώδικα. Στη συνέχεια, θα δούμε την εξήγηση γραμμή προς γραμμή.







#include
χρησιμοποιώντας χώρο ονομάτων std ;
ενθ κύριος ( κενός ) {
ενθ * Π ;
cout << * Π ;
}

Το πρόγραμμα ξεκινά με τη δήλωση της οδηγίας προεπεξεργαστή '#include ' και χρησιμοποιώντας το 'namespace std' που είναι απαραίτητο να συμπεριληφθούν στο πρόγραμμα για τη χρήση των τυπικών συναρτήσεων εισόδου και εξόδου. Μετά από αυτό, έρχεται το κύριο σημείο εισόδου που είναι 'int main(void);'. Αυτή η γραμμή δηλώνει το σημείο εκκίνησης του προγράμματος.



Μέσα στην κύρια συνάρτηση, δηλώνεται η μεταβλητή δείκτη «*p». Εδώ, η μεταβλητή 'p' δεν αρχικοποιείται. Ως εκ τούτου, δεν υποδεικνύει κάποια συγκεκριμένη θέση μνήμης που είναι δεσμευμένη για τον ακέραιο. Αυτή η γραμμή προκαλεί ένα σφάλμα το οποίο θα επιλύσουμε αργότερα. Στην επόμενη γραμμή, επιχειρούμε να εκτυπώσουμε την τιμή της μεταβλητής '*p' χρησιμοποιώντας τη δήλωση 'cout'.



Δεδομένου ότι η μεταβλητή 'p' είναι δείκτης ακέραιου τύπου, ο αστερίσκος '*' χρησιμοποιείται για την αποαναφορά της. Αυτό σημαίνει ότι η τιμή βρίσκεται στη θέση μνήμης στην οποία δείχνει. Ωστόσο, επειδή ο δείκτης 'p' δεν αρχικοποιήθηκε και δεν δείχνει σε κάποια συγκεκριμένη και έγκυρη θέση, η αποσύνδεση του δείκτη θα έχει ως αποτέλεσμα απροσδιόριστη συμπεριφορά. Ως εκ τούτου, έχει ως αποτέλεσμα τη δημιουργία διαφόρων ειδών σφαλμάτων ανάλογα με το σύστημα και τον μεταγλωττιστή. Εφόσον χρησιμοποιούμε τον μεταγλωττιστή GDB για τον εντοπισμό σφαλμάτων και την εκτέλεση αυτού του προγράμματος, το πρόγραμμα εντοπισμού σφαλμάτων θα εμφανίσει το ακόλουθο σφάλμα. Το σφάλμα εμφανίζεται στο απόσπασμα εξόδου:





Όπως μπορείτε να δείτε στην έξοδο, το πρόγραμμα εντοπισμού σφαλμάτων δεν μπορεί να έχει πρόσβαση στη μνήμη. Αυτό το πρόγραμμα αποαναφορίζει έναν μη αρχικοποιημένο δείκτη, τον κύριο λόγο για αυτήν την απροσδιόριστη συμπεριφορά. Τώρα, ας δούμε πώς μπορούμε να λύσουμε αυτό το πρόβλημα. Ο σωστός κωδικός δίνεται παρακάτω. Ρίξτε μια ματιά σε αυτό και θα εξηγήσουμε πώς διορθώνουμε το σφάλμα στον κώδικα:



#include
χρησιμοποιώντας χώρο ονομάτων std ;
ενθ κύριος ( κενός ) {
ενθ val = 5 ;
ενθ * Π = & val ;
cout << 'Η τιμή είναι =' << * Π ;

}

Όπως μπορείτε να δείτε, ο κώδικας τροποποιείται συμπεριλαμβάνοντας το 'int val =5;' δήλωση. Αυτή η γραμμή δηλώνει μια ακέραια μεταβλητή με το όνομα 'val' και την αρχικοποιεί με τιμή '5'. Η επόμενη γραμμή, 'int *p = &val;', δηλώνει μια μεταβλητή δείκτη '*p' και αρχικοποιείται για να δείχνει τη διεύθυνση της μεταβλητής 'val'. Προηγουμένως, ο δείκτης '*p' δεν έδειχνε καμία διεύθυνση μνήμης που προκαλούσε την 'αδυναμία πρόσβασης στη μνήμη στη διεύθυνση 0x0'.

Για να λυθεί αυτό το ζήτημα, η μεταβλητή 'var' δηλώνεται, αρχικοποιείται και εκχωρείται στον δείκτη '*p'. Τώρα, ο δείκτης '*p' δείχνει τη διεύθυνση της μεταβλητής 'val' καθώς ο τελεστής '&' παίρνει τη διεύθυνση 'val' και την εκχωρεί στο 'p'. Και πάλι, η δήλωση 'cout' χρησιμοποιείται για την εκτύπωση της τιμής του δείκτη '*p'. Δείτε το παρακάτω απόσπασμα εξόδου για να δείτε την τιμή του 'val' στην οποία προσπελάζεται ο δείκτης '*p':

Όπως μπορείτε να παρατηρήσετε, το σφάλμα έχει επιλυθεί και η τιμή του '5' αρχικοποιείται αφού η μεταβλητή 'val' έχει εκτυπωθεί καλώντας τον δείκτη '*p' valribale.

Παράδειγμα 2:

Ας εξετάσουμε ένα άλλο παράδειγμα που εξηγεί τον τρόπο αντιμετώπισης του σφάλματος 'Το GDB δεν έχει πρόσβαση στη μνήμη στη διεύθυνση' στο πρόγραμμα κώδικα C++. Ο κωδικός δίνεται παρακάτω για αναφορά σας. Κοίτα:

#include
ενθ κύριος ( ) {
ενθ * Π = νέος ενθ [ δεκαπέντε ] ;
διαγράφω [ ] Π ;
std :: cout << Π [ 2 ] << std :: endl ;
ΕΠΙΣΤΡΟΦΗ 0 ;
}

Ένα από τα πιο συνηθισμένα σενάρια που αντιμετωπίζουν οι προγραμματιστές κατά τον προγραμματισμό με δείκτες είναι η λανθασμένη ή ακατάλληλη εκχώρηση μνήμης. Το GDB έχει ως αποτέλεσμα το σφάλμα κάθε φορά που εμφανίζεται λανθασμένη εκχώρηση μνήμης και κατανομή σε ένα πρόγραμμα C++.

Λαμβάνοντας υπόψη το προηγούμενο παράδειγμα κώδικα, ένας δείκτης '*p' αρχικοποιείται με ένα νέο int[15]. Αυτή η δήλωση εκχωρεί δυναμικά έναν πίνακα 15 ακεραίων χρησιμοποιώντας τον νέο τελεστή. Η μεταβλητή δείκτη «*p» αποθηκεύει τη διεύθυνση μνήμης του πίνακα.

Στην ακόλουθη δήλωση, το 'delete[] p;,' δηλώνει ότι η μνήμη έχει εκχωρηθεί χρησιμοποιώντας την εντολή delete[]. Η εντολή delete[] εκχωρεί την προηγουμένως εκχωρηθείσα μνήμη του δείκτη '*p', που σημαίνει ότι το άλλο σύστημα χρησιμοποιεί το μπλοκ μνήμης που είχε εκχωρηθεί ξανά. Όταν επιχειρούμε να εκτυπώσουμε την τιμή της μεταβλητής '*p' χρησιμοποιώντας τη δήλωση 'cout', θα λάβουμε το σφάλμα πρόσβασης στη μνήμη όπως φαίνεται στην ακόλουθη έξοδο:

Τα πράγματα που πρέπει να έχετε κατά νου εδώ είναι ότι το ακριβές μήνυμα σφάλματος ενδέχεται να διαφέρει ελαφρώς ανάλογα με την έκδοση και το σύστημά σας GDB. Αλλά το 'σφάλμα: Το GDB δεν έχει πρόσβαση στη μνήμη στην τοποθεσία' και το σφάλμα που δίνεται στο προηγούμενο απόσπασμα είναι το ίδιο. Για να επιλύσουμε αυτό το σφάλμα, απλώς μετατοπίζουμε την εντολή delete[] μετά τη δήλωση 'cout'. Δείτε τον τροποποιημένο κώδικα στα παρακάτω:

#include
ενθ κύριος ( ) {
ενθ * Π = νέος ενθ [ δεκαπέντε ] ;
Για ( ενθ Εγώ = 0 ; Εγώ < δεκαπέντε ; ++ Εγώ ) {
Π [ Εγώ ] = Εγώ * 2 - 5 + 8 ;
std :: cout << 'Π[' << Εγώ << '] = ' << Π [ Εγώ ] << std :: endl ;
}
διαγράφω [ ] Π ;
ΕΠΙΣΤΡΟΦΗ 0 ;
}

Εδώ, μπορείτε να δείτε ότι αρχικοποιήσαμε τον πίνακα με τιμές που υπολογίζονται κατά το χρόνο εκτέλεσης και εκτυπώνουμε όλες τις τιμές του βρόχου χρησιμοποιώντας τον βρόχο 'for'. Το πιο σημαντικό πράγμα που πρέπει να σημειωθεί εδώ είναι η μετατόπιση της δήλωσης delete[]. καλείται τώρα αφού λάβει όλες τις τιμές του πίνακα που έχει αφαιρέσει το σφάλμα πρόσβασης στη μνήμη. Δείτε την τελική έξοδο του κώδικα στα παρακάτω:

συμπέρασμα

Συμπερασματικά, το σφάλμα 'σφάλμα: Το GDB δεν έχει πρόσβαση στη μνήμη στη διεύθυνση' συνήθως υποδεικνύει ζητήματα που σχετίζονται με τη μνήμη στον κώδικα C++. Αυτό το άρθρο διερεύνησε ορισμένα κοινά σενάρια που ξεκινούν αυτό το σφάλμα για να εξηγήσει πότε και πώς μπορεί να επιλυθεί. Όταν παρουσιάζεται αυτό το σφάλμα στον κώδικα, είναι απαραίτητο να το ελέγξετε προσεκτικά δίνοντας μεγάλη προσοχή στις μεταβλητές δείκτη, τις εκχωρήσεις μνήμης, τους πίνακες και τις δομές.

Επιπλέον, λειτουργίες όπως τα σημεία διακοπής που παρέχονται από το GDB μπορούν να βοηθήσουν στον εντοπισμό του σφάλματος κατά τον εντοπισμό σφαλμάτων του προγράμματος. Αυτά τα χαρακτηριστικά μπορούν να βοηθήσουν στον εντοπισμό της ακριβούς τοποθεσίας των σφαλμάτων που σχετίζονται με τη μνήμη. Αντιμετωπίζοντας αυτά τα ζητήματα προληπτικά, οι προγραμματιστές μπορούν να βελτιώσουν τη σταθερότητα και την αξιοπιστία των εφαρμογών τους C++.