Sobes.tech
Middle+

Τι γνωρίζετε για τις εγγυήσεις ασφαλείας των εξαιρέσεων;

sobes.tech AI

Απάντηση από AI

Οι εγγυήσεις ασφάλειας εξαιρέσεων καθορίζουν τη συμπεριφορά της λειτουργίας σε περίπτωση εμφάνισης εξαίρεσης. Διακρίνονται τέσσερα επίπεδα εγγυήσεων:

  1. Βασική εγγύηση (Basic guarantee): Αν η λειτουργία ρίξει εξαίρεση, το πρόγραμμα παραμένει σε έγκυρη κατάσταση. Οι πόροι δεν χάνονται (π.χ., η μνήμη απελευθερώνεται), αλλά η ακριβής κατάσταση των αντικειμένων μπορεί να είναι άγνωστη. Διατηρείται η δυνατότητα περαιτέρω εργασίας με την εφαρμογή.

    // Παράδειγμα βασικής εγγύησης
    void basic_guarantee_function(std::vector<int>& vec, int value) {
        // Μπορεί να προκύψουν εξαιρέσεις κατά την εισαγωγή
        vec.push_back(value); 
        // Αν προκύψει εξαίρεση, το vec μπορεί να βρίσκεται σε απρόβλεπτη κατάσταση (μερικώς τροποποιημένο),
        // αλλά η μνήμη που έχει δεσμευτεί για το vec θα απελευθερωθεί σωστά κατά την έξοδο από το πεδίο ορατότητας.
    } 
    
  2. Απαράμιλλη εγγύηση (Strong guarantee): Αν η λειτουργία ρίξει εξαίρεση, η κατάσταση του προγράμματος παραμένει ίδια με πριν από την κλήση της λειτουργίας. Όλες οι αλλαγές ανατρέπονται.

    // Παράδειγμα απαράμιλλης εγγύησης
    // Χρησιμοποιούμε το idiom Copy-and-Swap για την παροχή απαράμιλλης εγγύησης
    class Resource {
        int* data;
        size_t size;
    public:
        Resource(size_t s) : size(s), data(new int[s]) {}
        ~Resource() { delete[] data; }
        Resource(const Resource& other) : size(other.size), data(new int[other.size]) {
            std::copy(other.data, other.data + size, data); // Μπορεί να ρίξει εξαίρεση
        }
        Resource& operator=(Resource other) // Μεταφορά με τιμή
        {
            swap(*this, other); // Δεν ρίχνει εξαιρέσεις
            return *this;
        }
        friend void swap(Resource& first, Resource& second) noexcept {
            using std::swap;
            swap(first.data, second.data);
            swap(first.size, second.size);
        }
        // ... άλλα μέλη
    };
    
    void strong_guarantee_function(Resource& res, size_t new_size) {
        Resource temp(new_size); // Αν εδώ προκύψει εξαίρεση, το res δεν θα αλλάξει
        res = temp;               // Χρησιμοποιούμε τον υπερφορτωμένο operator=, που παρέχει απαράμιλλη εγγύηση
    }
    
  3. Εγγύηση χωρίς εξαίρεση (No-throw guarantee): Η λειτουργία δεν ρίχνει ποτέ εξαίρεση. Τέτοιες λειτουργίες σημειώνονται με τον ειδικό όρο noexcept.

    // Παράδειγμα χωρίς εξαίρεση
    void no_throw_function() noexcept {
        // Δεν υπάρχουν λειτουργίες που μπορούν να ρίξουν εξαίρεση
        int a = 5;
        int b = 10;
        int c = a + b;
    }
    
  4. Εγγύηση αποτυχίας (Failure guarantee): Στο πλαίσιο της ασφάλειας εξαιρέσεων, μερικές φορές αναφέρεται αυτό το επίπεδο, που σημαίνει ότι η λειτουργία μπορεί να αφήσει το πρόγραμμα σε μη ορισμένη κατάσταση, πιθανώς με διαρροή πόρων ή σφάλματα. Αυτό είναι ουσιαστικά η απουσία εγγυήσεων. Πρέπει να αποφεύγεται τέτοια συμπεριφορά.

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

Πίνακας σύγκρισης εγγυήσεων:

Εγγύηση Κατάσταση σε περίπτωση εξαίρεσης Ακεραιότητα δεδομένων Διαρροές πόρων
Βασική Έγκυρη, αλλά μη ορισμένη Δεν εγγυάται Όχι
Απαράμιλλη Μη μεταβλητή (όπως πριν από την κλήση) Διατηρείται Όχι
Χωρίς εξαίρεση Ποτέ δεν συμβαίνει (χωρίς εξαιρέσεις) N/A N/A
Αποτυχία (απουσία) Μη ορισμένη, πιθανώς με ζημιά ή σφάλματα Δεν εγγυάται Μπορεί