Fatal Error: τι είναι, κύριες αιτίες και τρόποι πρόληψης

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-05-27 Χρόνος ανάγνωσης: 8 λεπ

Fatal Error — είναι ένα κρίσιμο σφάλμα που οδηγεί σε άμεση διακοπή της λειτουργίας της εφαρμογής (crash). Σε αντίθεση με το non-fatal error, το θανατηφόρο σφάλμα δεν αφήνει στο πρόγραμα δυνατότητα ανάκτησης — η διεργασία τερματίζεται απότομα από το λειτουργικό σύστημα ή το περιβάλλον χρόνου εκτέλεσης (runtime). Σύμφωνα με τα δεδομένα Firebase Crashlytics 2024, η μέση εφαρμογή χάνει 2.5% των χρηστών μετά από κάθε crash, και η επίλυση των θανατηφόρων σφαλμάτων αποτελεί προτεραιότητα νούμερο ένα στην ανάπτυξη εφαρμογών κινητών. Όσο υψηλότερο είναι το crash-free rate, τόσο υψηλότερη η αβαθμολόγηση της εφαρμογής στα καταστήματα και τόσο μικρότερη η απορροή χρηστών.

Κύρια σημεία

  • Fatal Error — κρίσιμο σφάλμα που προκαλεί άμεση κατάρρευση της εφαρμογής
  • Null-pointer — η συχνότερη αιτία θανατηφόρων σφαλμάτων σε εφαρμογές κινητών
  • Non-Fatal Error — εναλλακτικός τύπος σφάλματος που δεν τερματίζει την εφαρμογή
  • Crashlytics και Sentry συλλέγουν αυτόματα τα stack traces θανατηφόρων σφαλμάτων
  • Πρόληψη fatal σφαλμάτων περιλαμβάνει safe unwrapping, defensive programming και δοκιμές

Τι είναι το Fatal Error

Fatal Error — είναι ένα σφάλμα κατά το οποίο η περαιτέρω εκτέλεση του προγράμματος είναι αδύνατη. Το λειτουργικό σύστημα ή η εικονική μηχανή τερματίζει τη διεργασία για να αποτραπεί η ζημιά δεδομένων. Στο iOS, το θανατηφόρο σφάλμα προκαλεί σήμα SIGABRT ή SIGSEGV, στο Android — μη επεξεργασμένη εξαίρεση που φτάνει στον ριζικό χειριστή και τερματίζει τη διεργασία. Η εφαρμογή κλείνει αμέσως και ο χρήστης επιστρέφει στην Αρχική Οθόνη.

Σημεία θανατηφόρου σφάλματος

Τα χαρακτηριστικά σημεία ενός θανατηφόρου σφάλματος: crash report με πλήρες stack trace, απροσδόκητη εξαφάνιση της εφαρμογής, εγγραφή στο system log για τερματισμό της διεργασίας, μαύρη ή άσπρη οθόνη πριν το κλείσιμο. Ο χρήστης βλέπει την Αρχική Οθόνη χωρίς δυνατότητα αποκατάστασης της συνεδρίας — η εφαρμογή πρέπει να επανεκκινηθεί από την αρχή. Στο iOS, το crash συνοδεύεται από εγγραφή σε αρχείο .crash, προσβάσιμο μέσω Xcode Organizer.

Επίδραση σε επιχειρηματικές μετρικές

Κάθε crash επηρεάζει αρνητικά το user retention. Σύμφωνα με το Google Play Console 2024, εφαρμογές με crash-free rate κάτω από 99.5% λαμβάνουν μειωμένη βαθμολογία στην αναζήτηση και στις συστάσεις. Το crash-rate είναι ένα από τα κλειδικά σήματα ποιότητας για το App Store και το Google Play — το υψηλό επίπεδο θανατηφόρων σφαλμάτων μπορεί να αποκλείσει την δημοσίευση ενημερώσεων. Για χρηματοοικονομικές και ιατρικές εφαρμογές, το crash-free rate κάτω από 99.9% θεωρείται απαράδεκτο.

Αιτίες θανατηφόρων σφαλμάτων

Null-pointer dereference — η κυριάρχει αιτία θανατηφόρων σφαλμάτων σε εφαρμογές κινητών. Η προσπάθεια πρόσβασης σε ιδιότητα ή μέθοδο ενός αντικειμένου που είναι null προκαλεί NullPointerException στο Android ή EXC_BAD_ACCESS στο iOS. Σύμφωνα με τα δεδομένα JetBrains 2023, περίπου 28% όλων των production crashes σχετίζονται με null pointers. Στο Kotlin, το σύστημα null-safety μειώνει σημαντικά αυτό το ποσοστό, αλλά το force unwrap και η συμβατότητα με Java παραμένουν πηγές προβλήματος.

Index-out-of-bounds

Πρόσβαση σε στοιχείο συλλογής με μη υπάρχον ευρετήριο — η δεύτερη συχνότερη αιτία crashes. Στη Java και στο Kotlin είναι ArrayIndexOutOfBoundsException, στο Swift — fatal error: Index out of range. Συνήθως προκύπτει κατά την εργασία με λίστες μετά από φιλτράρισμα ή δυναμική αλλαγή του μεγέθους της συλλογής. Η χρήση ασφαλών μεθόδων όπως getOrNull (Kotlin) ή indices.contains (Swift) αποτρέπει αυτόν τον τύπο θανατηφόρων σφαλμάτων.

Resource-related crashes

Έλλειψη μνήμης (OutOfMemoryError), υπερχείλιση στίβας (StackOverflowError), φόρτωση μη υπάρχοντος πόρου — resource σφάλματα συχνά είναι θανατηφόρα και δύσκολο να αναπαραχθούν. Το OutOfMemoryError προκύπτει κατά τη φόρτωση μεγάλων εικόνων χωρίς συμπίεση ή λόγω διαρροής μνήμης από μη απελευθερωμένες αναφορές. Το StackOverflowError προκύπτει από βαθεία αναδρομή χωρίς βασική περίπτωση ή από κυκλικές κλήσεις σε αλυσίδες εντολών.

Concurrency σφάλματα

Deadlock, race condition, τροποποίηση συλλογής κατά τη διάρκεια της επανάληψης — σφάλματα πολλαπλών νημάτων εκδηλώνονται μη ντετερμινιστικά και είναι τα πιο δύσκολα στη διάγνωση. Στο Android, ConcurrentModificationException κατά τροποποίηση ArrayList από διαφορετικά νήματα, στο iOS crash από τροποποίηση NSMutableArray χωρίς συγχρονισμό. Η χρήση coroutines Kotlin (structured concurrency) ή Swift Actors (iOS 16+) μειώνει την πιθανότητα concurrency crashes.

Fatal Error vs Non-Fatal Error

Η κλειδική διαφορά είναι η δυνατότητα ανάκτησης. Το Non-Fatal Error επιτρέπει στο πρόγραμα να συνεχίσει τη λειτουργία του: το χρονικό όριο δικτύου επεξεργάζεται με try-catch, το σφάλμα ανάλυσης αντικαθίσταται με προκαθορισμένη τιμή. Το Fatal Error δεν έχει τέτοια διαδρομή — το crash είναι αναπόφευκτο και η εφαρμογή πρέπει να επανεκκινηθεί. Το όριο μεταξύ αυτών των δύο τύπων σφαλμάτων καθορίζεται από την αρχιτεκτονική της εφαρμογής.

ΧαρακτηριστικόFatal ErrorNon-Fatal Error
Τερματισμός εφαρμογήςΝαιΌχι
ΑνάκτησηΑδύνατηΕπιτρεπτή μέσω catch-block
Συλλογή πληροφοριώνΜόνο crash reporterΚαταγραφή από τον κώδικα
Ζημία UXΠλήρης αποτυχία συνεδρίαςΠροσωρινή ενόχληση
Τυπικό παράδειγμαNullPointerExceptionIOException

Το ίδιο σφάλμα μπορεί να είναι fatal σε μία πλατφόρμα και non-fatal σε μία άλλη. Η διαίρεση διά του μηδενός σε Java/Kotlin προκαλεί ArithmeticException (μη θανατηφόρο — μπορεί να πιαστεί), στο Swift προκαλεί fatal error: Division by zero (crash χωρίς δυνατότητα πίασης). Ο αναπτυκτής πρέπει να λαμβάνει υπόψη τη συμπεριφορά της συγκεκριμένης γλώσσας και του περιβάλλοντος χρόνου εκτέλεσης κατά τον σχεδιασμό χειρισμού σφαλμάτων. Η κατανόηση του ορίου μεταξύ fatal και non-fatal αποτελεί τη βάση για την ανοχή σφαλμάτων στην αρχιτεκτονική εφαρμογών κινητών.

Διάγνωση θανατηφόρων σφαλμάτων

Firebase Crashlytics — το πρότυπο de facto για τη διάγνωση crashes σε εφαρμογές κινητών. Το SDK συλλέγει αυτόματα το stack trace, την κατάσταση της συσκευής, την έκδοση ΛΟΣ και τα αρχεία καταγραφής αμέσως πριν από το crash. Το Dashboard ομαδοποιεί τα παρόμοια crashes σε μία αντιμετώπιση, εμφανίζοντας τον αριθμό των επηρεασμένων χρηστών, τη συχνότητα εμφάνισης και την έκδοση της εφαρμογής στην οποία συνέβη το crash.

kotlin
// Αρχικοποίηση Crashlytics σε εφαρμογή Android
class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        FirebaseApp.initializeApp(this)
        Crashlytics.setCustomKey("build_type", "production")
    }
}

// Ορισμός προσαρμοσμένων δεδομένων χρήστη για διαγνωστικά crash
Crashlytics.setUserId("user_12345")
Crashlytics.setCustomKey("screen", "ProfileFragment")
Crashlytics.setCustomKey("api_response", responseCode)

// Αναγκαστικό crash για δοκιμή ενσωμάτωσης
Crashlytics.crash()

Sentry — εναλλακτική λύση με πιο λεπτομερή διάγνωση. Το Sentry δείχνει όχι μόνο το stack trace, αλλά και την κατάσταση όλων των μεταβλητών, την ακολουθία γεγονότων πριν από το σφάλμα και το περιεχόμενο εκτέλεσης. Τα Breadcrumbs του Sentry επιτρέπουν την ανασύνταξη της αλυσίδας ενεργειών του χρήστη πριν από το θανατηφόρο σφάλμα: πατήματα κουμπιών, μεταβάσεις μεταξύ οθονών, αιτήσεις δικτύου. Στο Sentry διατίθεται παρακολούθηση απόδοσης και συνεδριών για ολοκληρωμένη ανάλυση ποιότητας.

Symbology και απομποποίηση

Για τη σωστή διάγνωση crashes στο iOS απαιτείται η φόρτωση dSYM αρχείων (debug symbols) στο Crashlytics ή Sentry. Χωρίς dSYM, το stack trace θα περιέχει μόνο διευθύνσεις μνήμης αντί για ονόματα συναρτήσεων. Για Android απαιτείται η φόρτωση mapping αρχείων κατά τη χρήση ProGuard ή R8. Η αυτοματοποίηση φόρτωσης dSYM μέσω build phase στο Xcode ή Gradle plugin είναι υποχρεωτική για τις production εκδόσεις.

Πρόληψη θανατηφόρων σφαλμάτων

Βασική μέθοδος πρόληψης — το safe unwrapping όλων των προαιρετικών και nullable τιμών. Η χρήση if-let στο Swift και let με ?: στο Kotlin εξαλείφει τα σφάλματα null-pointer. Καμία force unwrap χωρίς εγγύηση υπαρξης της τιμής. Τος συμπεριφτατής Kotlin και Swift προειδοποιούν για δυνητικά επικίνδυνες λειτουργίες — αυτές οι προειδοποιήσεις δεν πρέπει να αγνοούνται σε production κώδικα.

swift
// ΠΡΟΛΗΨΗ fatal error μέσω safe unwrapping
func processUser(id: String) -> String {
    guard let user = database.findUser(by: id) else {
        return "User not found"
    }
    guard let email = user.email else {
        return "Email not set"
    }
    return email
}

// Ασφαλής πρόσβαση σε στοιχεία συλλογής
func safeGet <T>(items: [T], index: Int) -> T? {
    guard items.indices.contains(index) else { return nil }
    return items[index]
}

// Έλεγχος ορίων πίνακα πριν από την πρόσβαση
let numbers = [1, 2, 3]
if numbers.indices.contains(5) {
    print(numbers[5])
} else {
    print("Index out of range")
}

Defensive programming — το δεύτερο επίπεδο προστασίας. Ελέγχετε πάντα τις εισαγωγες παραμέτρους των συναρτήσεων, επιστρέφετε Optional ή Result αντί για force unwrap, χρησιμοποιείτε assert σε debug εκδόσεις για έγκαιρη ανίχνευση σφαλμάτων κατά τη φάση ανάπτυξης. Τα Unit tests σε οριακές περιπτώσεις (null, κενές συλλογές, λανθασμένα ευρετήρια) πρέπει να καλύπτουν όλα τα δημόσια σημεία εισόδου στην επιχειρηματική λογική της εφαρμογής.

Error Boundary για το UI layer

Σε React Native και SwiftUI μπορείτε να ορίσετε ένα error boundary — ένα στοιχείο που πιάνει θανατηφόρα σφάλματα απόδοσης και εμφανίζει fallback UI αντί για crash. Αυτό μετατρέπει ένα θανατηφόρο UI σφάλμα σε non-fatal από την άποψη του χρήστη — η εφαρμογή συνεχίζει να λειτουργεί, και ο χρήστης βλέπει ένα μήνυμα σφάλματος σε ένα συγκεκριμένο τμήμα της διεπαφής, όχι μια άσπρη οθόνη.

Έλεγχοι CI/CD για crashes

Ενσωμάτωση αυτόματων ελέγχων στο CI/CD pipeline: στατική ανάλυση (Detekt για Kotlin, SwiftLint για Swift), εκτέλεση UI tests σε πραγματικές συσκευές, έλεγχος crash-free rate σε δοκιμαστικό περιβάλλον. Παραγγελία συγχώνευσης κατά την υπέρβαση του ορίου crash-rate (συνιστώμενο όριο — παραπάνω 0.1% νέων crashes ανά commit).

Συχνές ερωτήσεις

Μπορώ να ανακτήσω μετά από fatal error;

Όχι, μετά από fatal error η ανάκτηση είναι αδύνατη — η διεργασία τερματίζεται σε επίπεδο ΛΟΣ. Ο μόνος τρόπος είναι να αποτραπεί το θανατηφόρο σφάλμα πριν εμφανιστεί μέσω ασφαλών κατασκευών, defensive programming και επισταμένης δοκιμής οριακών περιπτώσεων κατά τη φάση ανάπτυξης.

Σε τι διαφέρει το fatal error από το segfault;

Segfault (SIGSEGV) — είναι ένας τύπος fatal error, που προκύπτει κατά την πρόσβαση σε μη επιτρεπόμενη περιοχή μνήμης. FATAL ERROR είναι η γενική έννοια για όλα τα μη ανακτήσιμα σφάλματα, συμπεριλαμβανομένων segfault, abort, stack overflow, out of memory και μη επεξεργασμένων εξαιρέσεων κατά τη συνέχεια.

Πώς συλλέγω αυτόματα fatal errors σε production;

Η ενσωμάτωση Crashlytics (Firebase) ή Sentry SDK συλλέγει αυτόματα όλες τις μη επεξεργασμένες εξαιρέσεις. Το SDK πιάνει σήματα ΛΟΣ και εξαιρέσεις χρόνου εκτέλεσης, δημιουργεί αναφορά crash με stack trace και περιεχόμενο και την αποστέλλει στον διακομιστή κατά την επόμενη εκκίνηση της εφαρμογής.

Πώς δοκιμάζω σενάρια με fatal error;

Για τη δοκιμή χειρισμού crashes χρησιμοποιείται force crash σε debug έκδοση. Το Crashlytics παρέχει τη μέθοδο crash() για την εξομοίωση ενός θανατηφόρου σφάλματος. Σε unit tests ελέγχεται η ορθότητα guard και if-let, ενώ UI tests καλύπτουν οριακές περιπτώσεις εισαγωγής δεδομένων και κατάστασης διεπαφής.

Όλες οι εξαιρέσεις είναι fatal σε εφαρμογές κινητών;

Όχι, μόνο οι μη επεξεργασμένες εξαιρέσεις γίνονται θανατηφόρες. Μία εξαίρεση που πιάνεται από try-catch είναι non-fatal. Η διαφορά ανάμεσα σε μια επεξεργασμένη και μη επεξεργασμένη εξαίρεση καθορίζει αν η εφαρμογή θα τερματιστεί ή θα συνεχίσει με εναλλακτική κατάσταση με ελάχιστη ζημία για την εμπειρία του χρήστη.

Σύνοψη

  • Fatal Error — μη ανακτήσιμο σφάλμα που προκαλεί crash και τερματισμό της διεργασίας της εφαρμογής
  • Null-pointer — η κύρια αιτία θανατηφόρων σφαλμάτων (28% όλων των production crashes σύμφωνα με JetBrains)
  • Non-Fatal Error — επεξεργασμένη εξαίρεση, δεν τερματίζει την εφαρμογή (χρονικό όριο δικτύου, parse error)
  • Crashlytics — το κύριο εργαλείο για αυτόματη συλλογή και ανάλυση crashes σε εφαρμογές κινητών
  • Safe unwrapping — βασική μέθοδος πρόληψης θανατηφόρων σφαλμάτων σε Swift και Kotlin
  • Defensive programming — έλεγχος εισαγωγών, ευρετηρίων και οριακών καταστάσεων
  • Error Boundary — στοιχείο που μετατρέπει ένα θανατηφόρο UI σφάλμα σε non-fatal για τον χρήστη

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης