Στοίβα κλήσεων

Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια

Στην επιστήμη της πληροφορικής, η στοίβα κλήσεων (call stack) είναι μια δομή δεδομένων στοίβας που κρατά πληροφορίες σχετικά με τις ενεργές υπορουτίνες ενός προγράμματος. Αυτός ο τύπος στοίβας είναι γνωστός και σαν στοίβα εκτέλεσης (execution stack), στοίβα ελέγχου (control stack), στοίβα συναρτήσεων (function stack), ή στοίβα χρόνου εκτέλεσης (run-time stack), και συχνά αναφέρεται απλά σαν «η στοίβα». Αν και η συντήρηση της στοίβας κλήσεων είναι σημαντική για τη σωστή λειτουργία των πιο πολλών προγραμμάτων, οι λεπτομέρειες συνήθως είναι αόρατες στις γλώσσες υψηλού επιπέδου.

Μια στοίβα κλήσεων χρησιμοποιείται για πολλούς σχετικούς μεταξύ τους σκοπούς, αλλά ο κύριος λόγος που υπάρχει είναι για να παρακολουθείται το σημείο στο οποίο κάθε ενεργή υπορουτίνα θα επιστρέψει τον έλεγχο όταν τελειώσει η εκτέλεσή της (ενεργές υπορουτίνες είναι αυτές που έχουν κληθεί αλλά ακόμα δεν έχει τελειώσει η εκτέλεσή τους, επιστρέφοντας). Αν, για παράδειγμα μια υπορουτίνα DrawSquare καλεί μια υπορουτίνα DrawLine από τέσσερα διαφορετικά σημεία, ο κώδικας της DrawLine πρέπει με κάποιον τρόπο να γνωρίζει πού να επιστρέψει. Αυτό συνήθως γίνεται με κώδικα για κάθε κλήση μέσα στην DrawSquare που τοποθετεί τη διεύθυνση στη μνήμη (της "διεύθυνσης επιστροφής") μιας εντολής στη στοίβα κλήσεων μετά την εντολή της κλήσης.

Περιγραφή[Επεξεργασία | επεξεργασία κώδικα]

Επειδή η στοίβα κλήσεων έχει την οργάνωση στοίβας, ο κώδικας που κάνει την κλήση σπρώχνει(pushes) τη διεύθυνση επιστροφής στη στοίβα, και η καλούμενη υπορουτίνα, όταν τελειώσει, επαναφέρει(pops) τη διεύθυνση επιστροφής από την κορυφή της στοίβας κλήσεων και μεταφέρει τον έλεγχο σε αυτήν τη διεύθυνση. Αν μια καλούμενη υπορουτίνα καλέσει μια άλλη υπορουτίνα, θα σπρώξει άλλη μια διεύθυνση επιστροφής στη στοίβα κλήσεων, και με αυτόν τον τρόπο το πρόγραμμα, η πληροφορία μπαίνει και βγαίνει από την κορυφή της στοίβας, κατά τις εντολές του προγράμματος. Αν η εισαγωγή νέων διευθύνσεων κάποια στιγμή καταναλώσει όλο το διαθέσιμο χώρο που έχει δεσμευτεί για τη στοίβα κλήσεων, προκύπτει ένα σφάλμα που ονομάζεται "υπερχείλιση στοίβας" ("stack overflow"), με αποτέλεσμα συνήθως το πρόγραμμα να τερματίζεται εσφαλμένα. Κάποιες φορές η προσθήκη στη στοίβα μιας εγγραφής για μια υπορουτίνα ονομάζεται τύλιγμα (winding), αντίστοιχα η αφαίρεσή της ονομάζεται ξετύλιγμα (unwinding).

Συνήθως υπάρχει μια λίστα σχετική με ένα πρόγραμμα που εκτελείται (ή, πιο σωστά, με κάθε εργασία ή νήμα μιας διεργασίας), αν και επιπλέον στοίβες μπορούν να δημιουργηθούν από το χειρισμό σημάτων ή τη συνεργατική πολυδιεργασία (όπως με τη setcontext). Από τη στιγμή που υπάρχει μόνο ένα σημαντικό περιβάλλον, αυτό ονομάζεται η στοίβα (εννοώντας "της εργασίας").

Στις γλώσσες υψηλού επιπέδου, οι λεπτομέρειες της στοίβας κλήσεων είναι κρυμμένες από τον προγραμματιστή. Υπάρχει μόνο πρόσβαση στη λίστα των συναρτήσεων και όχι στη μνήμη της ίδιας της στοίβας. Οι περισσότερες συμβολικές γλώσσες, όμως, απαιτούν από τον προγραμματιστή να συμμετέχει στο χειρισμό της στοίβας. Οι πραγματικές λεπτομέρειες της στοίβας σε μια γλώσσα προγραμματισμού εξαρτώνται από το μεταγλωττιστή, το λειτουργικό σύστημα και το διαθέσιμο σύνολο εντολών.

Λειτουργίες της στοίβας κλήσεων[Επεξεργασία | επεξεργασία κώδικα]

Όπως σημειώθηκε παραπάνω ο κύριος σκοπός μιας στοίβας κλήσεων είναι:

  • Η αποθήκευση της διεύθυνσης επιστροφής – Όταν καλείται μια υπορουτίνα, η θέση της εντολής στην οποία θα επιστρέψει πρέπει να αποθηκευτεί κάπου. Η χρήση της στοίβας για την αποθήκευση της διεύθυνσης επιστροφής έχει σημαντικά πλεονεκτήματα έναντι των άλλων εναλλακτικών. Ένα από αυτά είναι ότι κάθε εργασία έχει τη δική της στοίβα και επομένως η υπορουτίνα μπορεί να έχει την ικανότητα επανεισόδου (είναι "reentrant"), δηλαδή μπορεί να είναι ενεργή ταυτόχρονα σε διαφορετικές εργασίες κάνοντας διαφορετικά πράγματα. Ένα άλλο πλεονέκτημα είναι ότι υποστηρίζεται αυτόματα η αναδρομή. Όταν μια συνάρτηση καλεί τον εαυτό της αναδρομικά, για κάθε ενεργοποίηση της συνάρτησης πρέπει να αποθηκευτεί μια διεύθυνση επιστροφής για την επιστροφή από κάθε τέτοια ενεργοποίηση. Αυτή η δυνατότητα προσφέρεται αυτόματα από τη στοίβα.

Μια στοίβα κλήσεων μπορεί να έχει επιπλέον λειτουργίες, ανάλογα με τη γλώσσα, το λειτουργικό σύστημα και το περιβάλλον της πλατφόρμας του υλικού. Κάποιες από αυτές μπορούν να είναι:

  • Αποθήκευση τοπικών δεδομένων – Μια υπορουτίνα συχνά χρειάζεται χώρο στη μνήμη για να αποθηκεύει τις τιμές τοπικών μεταβλητών, των μεταβλητών δηλαδή που είναι γνωστές μόνο μέσα στα όρια της ενεργής υπορουτίνας και δεν κρατούν τις τιμές τους μετά την επιστροφή από αυτή. Συχνά είναι πιο εύκολο να κρατείται χώρος για αυτή τη χρήση μετακινώντας την κορυφή της στοίβας ώστε να δημιουργηθεί ο απαραίτητος χώρος. Αυτό είναι πολύ γρήγορο σε σχέση με τη δέσμευση μνήμης στο σωρό. Να σημειωθεί ότι κάθε ξεχωριστή ενεργοποίηση μιας υπορουτίνας αποκτά το δικό της χώρο στη στοίβα για τοπικές μεταβλητές.
  • Πέρασμα παραμέτρων – Οι υπορουτίνες συχνά απαιτούν οι τιμές των παράμετρος να δίνονται από τον κώδικα που τις καλεί και συχνά ο χώρος για αυτές τις παραμέτρους βρίσκεται στη στοίβα. Γενικά αν υπάρχουν μόνο λίγες μικρές παράμετροι, οι καταχωρητές του επεξεργαστή θα χρησιμοποιηθούν για το πέρασμα των τιμών, αλλά αν υπάρχουν περισσότερες παράμετροι που να μπορούν να χειριστούν με αυτόν τον τρόπο, θα χρειαστεί χώρος στη μνήμη. Η στοίβα κλήσεων λειτουργεί καλά σαν ένα μέρος για αυτές τις παραμέτρους, ειδικά όταν κάθε κλήση σε μια υπορουτίνα, που θα έχει διαφορετικές τιμές για τις παραμέτρους της, θα αποκτήσει διαφορετικό χώρο στη στοίβα κλήσεων για αυτές τις τιμές.
  • Στοίβα αποτίμησης – Οι τελεστέοι για αριθμητικές ή λογικές πράξεις συχνά τοποθετούνται στους καταχωρητές και χρησιμοποιούνται από εκεί. Όμως, υπάρχουν καταστάσεις στις οποίες οι τελεστέοι μπορεί να βρίσκονται σε δομή στοίβας χωρίς όριο στο βάθος της, το οποίο σημαίνει ότι οι καταχωρητές δεν είναι αρκετοί. Η στοίβα αυτών των τελεστέων, όπως και αυτή μιας αριθμομηχανής RPN, αποκαλείται στοίβα αποτίμησης και μπορεί να καταλαμβάνει χώρο στη στοίβα κλήσεων.
  • Δείκτης στο τρέχον στιγμιότυπο - Κάποιες αντικειμενοστρεφείς γλώσσες (π.χ. η C++), αποθηκεύουν το δείκτη this μαζί με τα ορίσματα της συνάρτησης στη στοίβα κλήσεων όταν καλούν μεθόδους. Ο δείκτης this δείχνει στο αντικείμενο που ανήκει η μέθοδος που πρόκειται να κληθεί.
  • Περιβάλλον εξωτερικής υπορουτίνας - Κάποιες γλώσσες προγραμματισμού (π.χ. η Pascal και η Ada) υποστηρίζουν εμφωλευμένες υπορουτίνες, επιτρέποντας σε μια εσωτερική υπορουτίνα να έχει πρόσβαση στο περιβάλλον της εξωτερικής υπορουτίνας που την περιβάλλει, π.χ., στις παραμέτρους και στις τοπικές μεταβλητές μέσα στην εμβέλεια της εξωτερικής υπορουτίνας. Ένα τέτοιο στατικό φώλιασμα μπορεί να επαναλαμβάνεται - μια συνάρτηση που δηλώνεται μέσα σε μια άλλη συνάρτηση που δηλώνεται μέσα σε μια άλλη συνάρτηση... Η υλοποίηση πρέπει να παρέχει έναν τρόπο με τον οποίο η συνάρτηση που καλείται σε οποιοδήποτε επίπεδο φωλιάσματος να μπορεί να αναφέρεται σε κάθε πλαίσιο που την περικλείει. Συνήθως αυτή η αναφορά υλοποιείται με έναν δείκτη στο περιβάλλον πλαίσιο, που καλείται "downstack link" ή "στατικός σύνδεσμος"("static link"), για να διακρίνεται από το "δυναμικό σύνδεσμο" που αναφέρεται στη συνάρτηση που έκανε την τρέχουσα κλήση (η οποία όμως δεν αναγκαίο ότι είναι η στατική "γονική" συνάρτηση). Για παράδειγμα, οι γλώσσες συνήθως επιτρέπουν εσωτερικές ρουτίνες να καλούν τον εαυτό τους αναδρομικά, με αποτέλεσμα πολλαπλά πλαίσια κλήσεων για τις κλήσεις της εσωτερικής ρουτίνας, όλοι οι στατικοί σύνδεσμοι των οποίων θα δείχνουν στο ίδιο εξωτερικό περιβάλλον ρουτίνας. Αντί για στατικό σύνδεσμο, οι αναφορές στο περιβάλλον πλαίσιο μπορούν να συλλεγούν σε έναν πίνακα δεικτών γνωστό σαν display, οι θέσεις του οποίου δείχνουν τα επιθυμητά πλαίσια. Ο υπολογιστή Burroughs B6500 είχε ένα τέτοιο display, υλοποιημένο σε υλικό, που υποστήριζε μέχρι 32 επίπεδα στατικού φωλιάσματος.
  • Άλλη κατάσταση επιστροφής – Εκτός της διεύθυνσης επιστροφής, σε κάποια περιβάλλοντα υπάρχουν άλλα μέρη του υλικού ή καταστάσεις λογισμικού που πρέπει να γίνει επαναφορά τους όταν τελειώνει μια υπορουτίνα. Αυτό μπορεί να περιλαμβάνει πράγματα όπως το επίπεδο δικαιωμάτων (privilege level), πληροφορίες για το χειρισμό εξαιρέσεων, και καταστάσεις αριθμητικής. Αν είναι απαραίτητο αυτά μπορούν να αποθηκευτούν στη στοίβα κλήσεων όπως η διεύθυνση επιστροφής.

Η κλασική στοίβα κλήσεων χρησιμοποιείται για τη διεύθυνση επιστροφής, τις τοπικές μεταβλητές και τις παραμέτρους (και είναι γνωστή σαν πλαίσιο κλήσης / call frame). Σε κάποια περιβάλλοντα μπορεί να υπάρχουν περισσότερες ή λιγότερες λειτουργίες για τις οποίες να είναι υπεύθυνη η στοίβα. Στη γλώσσα προγραμματισμού Forth, για παράδειγμα, στη στοίβα αποθηκεύονται μόνο η διεύθυνση επιστροφής και οι τοπικές μεταβλητές (η στοίβα εκεί ονομάζεται στοίβα επιστροφής) - οι παράμετροι αποθηκεύονται σε μια ξεχωριστή στοίβα δεδομένων. Επίσης οι πιο πολλές εκδόσεις της Forth έχουν και μια τρίτη στοίβα για παραμέτρους κινητής υποδιαστολής.

Δομή[Επεξεργασία | επεξεργασία κώδικα]

Μια στοίβα κλήσεων αποτελείται από πλαίσια στοίβας (stack frames), γνωστά και ως εγγραφές δραστηριοποίησης (activation records) ή εγγραφές δραστηριοποίησης (activation frames). Αυτά είναι δομές δεδομένων ανεξάρτητες από την αρχιτεκτονική του υπολογιστή που περιλαμβάνουν πληροφορίες σχετικά με την κατάσταση των υπορουτινών. Κάθε πλαίσιο στοίβας αντιστοιχεί σε μια κλήση σε μια υπορουτίνα που δεν έχει ακόμα επιστρέψει. Για παράδειγμα, αν μια υπορουτίνα DrawLine εκτελείται, έχοντας μόλις κληθεί από μια υπορουτίνα DrawSquare, η κορυφή της στοίβας κλήσεων θα έχει την εξής διάταξη (όπου η στοίβα μεγαλώνει προς την κορυφή):

Το πλαίσιο στοίβας στην κορυφή της στοίβας αντιστοιχεί στη ρουτίνα που εκτελείται αυτήν τη στιγμή. Στην πιο κοινή περίπτωση το πλαίσιο στοίβας περιέχει:

  • χώρο για τις τοπικές μεταβλητές της ρουτίνας,
  • τη διεύθυνση επιστροφής πίσω στον κώδικα που κάλεσε τη ρουτίνα, και
  • τις τιμές των παραμέτρων που περάστηκαν στη ρουτίνα.

Η πρόσβαση στη στοίβα συχνά γίνεται μέσω ενός καταχωρητή που ονομάζεται δείκτης στοίβας (stack pointer), ο οποίος και επίσης χρησιμοποιείται για να δείχνει την κορυφή της στοίβας. Εναλλακτικά, η μνήμη μέσα στο πλαίσιο μπορεί να προσπελαστεί μέσω ενός ξεχωριστού καταχωρητή, που συχνά ονομάζεται δείκτης πλαισίου (frame pointer), ο οποίος συνήθως δείχνει σε μια σταθερή θέση στη δομή του πλαισίου, όπως η θέση της διεύθυνσης επιστροφής.

Τα πλαίσια στοίβας δεν έχουν πάντα το ίδιο μέγεθος. Διαφορετικές υπορουτίνες έχουν διαφορετικό αριθμό παραμέτρων, επομένως μέρος του πλαισίου στοίβας θα είναι διαφορετικό για διαφορετικές υπορουτίνες, αν και συνήθως σταθερό για όλες τις ενεργοποιήσεις μιας συγκεκριμένης υπορουτίνας. Όμοια, ο χώρος που χρειάζεται για τις τοπικές μεταβλητές θα είναι διαφορετικός για διαφορετικές υπορουτίνες. Στην πραγματικότητα, κάποιες γλώσσες επιτρέπουν τη δυναμική δέσμευση μνήμης για τοπικές μεταβλητές στη στοίβα, περίπτωση στην οποία το μέγεθος του χώρου για τις τοπικές μεταβλητές θα διαφέρει από ενεργοποίηση σε ενεργοποίηση μιας υπορουτίνας, και δεν είναι γνωστό όταν η υπορουτίνα μεταγλωττίζεται. Στην τελευταία αυτή περίπτωση, συνήθως χρειάζεται πρόσβαση μέσω ενός δείκτη πλαισίου και όχι δείκτη στοίβας, επειδή οι σχετικές θέσεις των τιμών (όπως η διεύθυνση επιστροφής) από την κορυφή δεν είναι γνωστές στο χρόνο μεταγλώττισης.

Σε πολλά συστήματα ένα πλαίσιο στοίβας έχει ένα πεδίο που περιέχει την προηγούμενη τιμή του καταχωρητή δείκτη πλαισίου, την οποία είχε κατά την εκτέλεση του κώδικα που τον κάλεσε. Για παράδειγμα, στο παραπάνω διάγραμμα, το πλαίσιο στοίβας της DrawLine θα είχε μια θέση μνήμης που θα κρατούσε το δείκτη πλαισίου που χρησιμοποιεί η DrawSquare. Η τιμή σώζεται κατά την είσοδο στην υπορουτίνα και επαναφέρεται κατά την επιστροφή από αυτή. Έχοντας ένα τέτοιο πεδίο σε μια γνωστή θέση στο πλαίσιο στοίβας, ο κώδικας μπορεί να έχει πρόσβαση σε κάθε πλαίσιο που βρίσκεται παρακάτω από το πλαίσιο της ρουτίνας που καλείται εκείνη τη στιγμή.

Οι γλώσσες προγραμματισμού που υποστηρίζουν εμφωλευμένες υπορουτίνες έχουν ένα πεδίο στο πλαίσιο κλήσης που δείχνει στο πλαίσιο κλήσης της εξωτερικής ρουτίνας που κάλεσε την εσωτερική. Αυτό κάποιες φορές ονομάζεται display[1]. Αυτός ο δείκτης επιτρέπει στην εσωτερική ρουτίνα (και σε όποιες ρουτίνες αυτή καλεί) να έχει πρόσβαση στις παραμέτρους και στις τοπικές μεταβλητές της εξωτερικής ρουτίνας που έκανε την κλήση.

Κατά κάποιον τρόπο, το πλαίσιο στοίβας μιας υπορουτίνας και του κώδικα που την καλεί μπορούν να θεωρηθούν ότι επικαλύπτονται, με την κοινή περιοχή να είναι εκεί που περνιούνται οι παράμετροι. Σε κάποια περιβάλλοντα, ο κώδικας που κάνει την κλήση σπρώχνει κάθε όρισμα στη στοίβα, επεκτείνοντας το πλαίσιο στοίβας, και στη συνέχεια καλεί τη συνάρτηση. Σε άλλα περιβάλλοντα, ο καλών διαθέτει μια ήδη δεσμευμένη περιοχή στην κορυφή της στοίβας για να κρατούνται εκεί τα ορίσματα που δίνει στις υπορουτίνες που καλεί. Αυτή η περιοχή μερικές φορές ονομάζεται περιοχή εξερχόμενων ορισμάτων (outgoing arguments area) ή callout area. Με αυτήν την προσέγγιση, το μέγεθος του χώρου υπολογίζεται από το μεταγλωττιστή να είναι το μεγαλύτερο που μπορεί να χρειαστεί κατά την κλήση κάποιας υπορουτίνας.

Χρήση[Επεξεργασία | επεξεργασία κώδικα]

Επεξεργασία θέσης κλήσης (call site processing)[Επεξεργασία | επεξεργασία κώδικα]

Συνήθως δε χρειάζεται κάποιος ιδιαίτερος χειρισμός της στοίβας κλήσεων στη θέση που καλείται μια υπορουτίνα (κάτι το οποίο είναι καλό - υπάρχουν πολλές θέσεις στις οποίες καλείται κάθε υπορουτίνα). Οι τιμές των πραγματικών ορισμάτων αποτιμώνται στη θέση κλήσης, μιας και αφορούν τη συγκεκριμένη κλήση, και είτε σπρώχνονται στη στοίβα, είτε τοποθετούνται σε καταχωρητές, ανάλογα με τη σύμβαση κλήσης που χρησιμοποιείται. Η πραγματική εντολή της κλήσης, π.χ. η "Branch and Link", εκτελείται στη συνέχεια για να μεταφέρει τον έλεγχο στην υπορουτίνα που κλήθηκε.

Επεξεργασία καλούμενου (callee processing)[Επεξεργασία | επεξεργασία κώδικα]

Στην υπορουτίνα που κλήθηκε, ο πρώτος κώδικας που καλείται λέγεται συνήθως ο πρόλογος υπορουτίνας, επειδή κάνει όλες τις απαραίτητες πράξεις πριν αρχίσει η εκτέλεση του κώδικα των εντολών της υπορουτίνας.

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

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

Η γλώσσα προγραμματισμού Forth επιτρέπει το ρητό ξετύλιγμα της στοίβας κλήσεων (που καλείται εκεί "στοίβα επιστροφής"). Η γλώσσα προγραμματισμού Scheme επιτρέπει το τύλιγμα ειδικών πλαισίων μέσα από ένα "δυναμικό τύλιγμα".

Επεξεργασία επιστροφής (return processing)[Επεξεργασία | επεξεργασία κώδικα]

Όταν μια υπορουτίνα είναι έτοιμη να επιστρέψει, εκτελεί έναν επίλογο που αναιρεί τις ενέργειες του προλόγου. Συνήθως επαναφέρει αποθηκευμένες τιμές των καταχωρητών (όπως η τιμή του δείκτη πλαισίου) από το πλαίσιο στοίβας, θα αφαιρέσει όλο το πλαίσιο στοίβας από τη στοίβα αλλάζοντας την τιμή του του δείκτη στοίβας και στο τέλος θα κάνει άλμα στην εντολή στη διεύθυνση επιστροφής. Κάτω από πολλές συμβάσεις κλήσης αυτά που αφαιρούνται από την κορυφή της στοίβας περιλαμβάνουν τις αρχικές τιμές των ορισμάτων, επομένως δε χρειάζεται να γίνουν άλλες ενέργειες στη στοίβα από τον κώδικα που έκανε την κλήση. Σε κάποιες συμβάσεις κλήσης όμως, είναι υποχρέωση του κώδικα που καλεί να αφαιρέσει τα ορίσματα από τη στοίβα πριν την επιστροφή.

Ξετύλιγμα[Επεξεργασία | επεξεργασία κώδικα]

Η επιστροφή από τη συνάρτηση που κλήθηκε θα αφαιρέσει το πλαίσιο στην κορυφή της στοίβας, ίσως αφήνοντας κάποια τιμή επιστροφής.

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

Κάποιες άλλες γλώσσες (όπως η Object Pascal) παρέχουν διαχείριση εξαιρέσεων, η οποία επίσης χρειάζεται ξετύλιγμα της στοίβας. Το πλαίσιο στοίβας μιας συνάρτησης περιέχει μια ή περισσότερες εγγραφές που ορίζουν κάποιους χειριστές εξαιρέσεων. Όταν εμφανίζεται μια εξαίρεση, η στοίβα ξετυλίγεται μέχρι να βρεθεί ένας χειριστής εξαιρέσεων που να μπορεί να χειριστεί (πιάσει) την εξαίρεση. Η Common Lisp επιτρέπει τον έλεγχο των ενεργειών που γίνονται όταν η στοίβα ξετυλίγεται χρησιμοποιώντας τον ειδικό τελεστή unwind-protect.

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

Στοίβες κλήσεων και δοκιμή λογισμικού[Επεξεργασία | επεξεργασία κώδικα]

Μια πρόσφατα δημοσιευμένη τεχνική [2] χρησιμοποιεί τις στοίβες κλήσεων με έναν αρκετά διαφορετικό τρόπο από αυτούς που προαναφέρθηκαν. Χρησιμοποιεί τις στοίβες κλήσεων για αναγωγή δοκιμών (test suite reduction). Εν συντομία, η αναγωγή δοκιμών προσπαθεί να μειώσει τον αριθμό των δοκιμαστικών περιπτώσεων σε μια δοκιμαστική σουίτα διατηρώντας ένα υψηλό ποσοστό της επιτυχίας σήμανσης λαθών της αρχικής σουίτας. Δυο δοκιμαστικές περιπτώσεις θεωρούνται ισοδύναμες αν δημιουργούν το ίδιο σύνολο στοιβών κλήσεων κατά τη διάρκεια της εκτέλεσης. Δείτε το [3] για περισσότερες λεπτομέρειες.

Ανάλυση της απόδοσης[Επεξεργασία | επεξεργασία κώδικα]

Η λήψη τυχαίων δειγμάτων από τη στοίβα κλήσεων μπορεί να είναι πολύ χρήσιμη στη βελτιστοποίηση της απόδοσης των προγραμμάτων. Αυτό συμβαίνει γιατί αν μια εντολή κλήσης μιας υπορουτίνας εμφανίζεται στη στοίβα κλήσεων για σημαντικό μέρος του χρόνου εκτέλεσης, η πιθανή αφαίρεσή της θα εξοικονομούσε αρκετό χρόνο. Δείτε Ανάλυση απόδοσης και Deep sampling.

Ασφάλεια[Επεξεργασία | επεξεργασία κώδικα]

Η ανάμειξη δεδομένων της ροής ελέγχου που επηρεάζουν την εκτέλεση κώδικα (διευθύνσεις επιστροφής, αποθηκευμένοι δείκτες σε πλαίσια) και απλών δεδομένων του προγράμματος (παράμετροι, τιμές επιστροφής) στη στοίβα κλήσεων αποτελεί κενό ασφάλειας που μπορεί κάποιες φορές να γίνει εκμετάλλευσή του με την τεχνική της υπερχείλισης ενταμιευτή (buffer overflow).

Δείτε επίσης[Επεξεργασία | επεξεργασία κώδικα]

Παραπομπές[Επεξεργασία | επεξεργασία κώδικα]

  1. c2:AlternativeMicroprocessorDesign
  2. “Call Stack Coverage for GUI Test-Suite Reduction” by Scott McMaster and Atif M. Memon. In Proceedings of the 17th IEEE International Symposium on Software Reliability Engineering (ISSRE 2006), Nov. 2006.
  3. “Call-Stack Coverage for GUI Test-Suite Reduction” by Scott McMaster and Atif M. Memon. IEEE Trans. Softw. Eng., 2008, IEEE Press.

Εξωτερικοί σύνδεσμοι[Επεξεργασία | επεξεργασία κώδικα]