Fatal Error — ово је критична грешка која доводи до тренутног престанка рада апликације (crash). За разлику од non-fatal error, фатална грешка не оставља програму могућност опоравка — процес се хитно завршава од стране оперативног система или runtime окружења. Према подацима Firebase Crashlytics 2024, просечна апликација губи 2.5% корисника после сваког crash-а, а отклањање фаталних грешака је приоритет број један у мобилном развоју. Што је crash-free rate виши, то је виши рејтинг апликације у продавницама и мањи је одлив корисника.
Главно
Fatal Error — је грешка при којој је даље извршење програма немогуће. Оперативни систем или виртуелна машина завршава процес како би спречили оштећење података. У iOS-у фатална грешка изазива сигнал SIGABRT или SIGSEGV, у Android-у — необрађени изузетак који стиже до коренског handler-а и завршава процес. Апликација се тренутно затвара, корисник се враћа на почетни екран.
Карактеристични знаци фаталне грешке: crash извештај са комплетним стектрејсом, неочекивани нестанак апликације, запис у системском логу о завршетку процеса, црни или бели екран пре затварања. Корисник види почетни екран без могућности обнављања сесије — апликација се мора покренути изнова из нултог стања. У iOS-у crash је праћен записом у .crash датотеку доступну преко Xcode Organizer-а.
Сваки crash негативно утиче на задржавање корисника. Према 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 crash-ева је повезано са null показивачима. У Kotlin-у null-safety систем значајно смањује овај проценат, али force unwrap и компатибилност са Java-ом остају извори проблема.
Приступ елементу колекције по непостојећем индексу — други по учесталости узрок crash-ева. У Java и Kotlin-у је то ArrayIndexOutOfBoundsException, у Swift-у — fatal error: Index out of range. Најчешће настаје при раду са листама након филтрирања или динамичке промене величине колекције. Коришћење безбедних метода getOrNull (Kotlin) или indices.contains (Swift) спречава овај тип фаталних грешака.
Недостатак меморије (OutOfMemoryError), прекорачење стека (StackOverflowError), учитавање непостојећег ресурса — грешке ресурса су често фаталне и тешко се репродукују. OutOfMemoryError настаје при учитавању великих слика без компресије или при цурењу меморије услед неослобођених референци. StackOverflowError — при дубокој рекурзији без базног случаја или при цикличним позивима у ланцу делегата.
Deadlock, race condition, модификација колекције током итерације — вишенитне грешке се манифестују недетерминистички и најтеже се дијагностикују. У Android-у ConcurrentModificationException при модификацији ArrayList-а из различитих нити, у iOS-у crash услед модификације NSMutableArray-а без синхронизације. Коришћење Kotlin корутина (structured concurrency) или Swift Actors (iOS 16+) смањује вероватноћу concurrency crash-ева.
Кључна разлика — могућност опоравка. Non-Fatal Error омогућава програму да настави рад: мрежни тајмаут се обрађује try-catch-ом, грешка парсирања се замењује подразумеваном вредношћу. Fatal Error нема такав пут — crash је неизбежан и апликација се мора поново покренути. Граница између ових типова грешака одређена је архитектуром апликације.
| Карактеристика | Fatal Error | Non-Fatal Error |
|---|---|---|
| Завршетак апликације | Да | Не |
| Опоравак | Немогућ | Могућ преко catch блока |
| Прикупљање информација | Само crash-репортер | Логовање из кода |
| UX штета | Потпуни губитак сесије | Привремена непријатност |
| Типичан пример | NullPointerException | IOException |
Иста грешка може бити фатална на једној платформи и non-fatal на другој. Дељење нулом у Java/Kotlin-у баца ArithmeticException (није фатално — може се ухватити), у Swift-у изазива fatal error: Division by zero (crash без могућности хватања). Програмер мора узети у обзир понашање конкретног језика и runtime окружења при пројектовању обраде грешака. Разумевање границе између fatal и non-fatal — основа изградње отпорне архитектуре мобилне апликације.
Firebase Crashlytics — де факто стандард за дијагностику crash-ева у мобилним апликацијама. SDK аутоматски прикупља стектрејс, стање уређаја, верзију оперативног система и логове непосредно пре crash-а. Dashboard групише идентичне crash-еве у један issue, показујући број погођених корисника, учесталост понављања и верзију апликације у којој се crash догодио.
// Иницијализација 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 показује не само стектрејс, већ и стање свих променљивих, след догађаја до грешке и контекст извршења. Breadcrumbs Sentry-а омогућавају обнављање ланца акција корисника пре фаталне грешке: притискање дугмади, прелази између екрана, мрежни захтеви. У Sentry-ју је доступно праћење перформанси и сесија за комплексну анализу квалитета.
За коректну дијагностику crash-ева на iOS-у потребно је учитавање dSYM датотека (debug symbols) у Crashlytics или Sentry. Без dSYM стектрејс ће садржати само меморијске адресе уместо имена функција. За 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 коду.
// СПРЕЧАВАЊЕ 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 верзијама за рано откривање грешака у фази развоја. Јединични тестови за граничне случајеве (null, празне колекције, неисправни индекси) треба да покривају све јавне улазне тачке пословне логике апликације.
У React Native и SwiftUI-ју се може поставити error boundary — компонента која хвата фаталне грешке рендеровања и приказује fallback UI уместо crash-а. Ово претвара фаталну UI грешку у non-fatal са становишта корисничког искуства — апликација наставља да ради, а корисник види поруку о грешци у конкретном блоку интерфејса, а не бели екран.
Интеграција аутоматских провера у CI/CD pipeline: статичка анализа (Detekt за Kotlin, SwiftLint за Swift), покретање UI тестова на реалним уређајима, провера crash-free rate у тестном окружењу. Блокирање merge-а при прекорачењу прага crash-rate (препоручени праг — више од 0.1% нових crash-ева по commit-у).
Често постављана питања
Не, после fatal error-а опоравак је немогућ — процес се завршава на нивоу оперативног система. Једини начин — спречити фаталну грешку пре њеног настанка кроз безбедне конструкције, defensive programming и свеобухватно тестирање граничних случајева у фази развоја.
Segfault (SIGSEGV) — један од типова fatal error-а, који настаје при приступу недозвољеној меморијској области. FATAL ERROR — општи појам за све неповратне грешке, укључујући segfault, abort, stack overflow, out of memory и необрађене изузетке у runtime-у.
Интеграција Crashlytics (Firebase) или Sentry SDK аутоматски прикупља све необрађене изузетке. SDK хвата сигнале оперативног система и runtime изузетке, формира crash извештај са стектрејсом и контекстом и шаље га на сервер при следећем покретању апликације.
За тестирање обраде crash-ева користи се force crash у debug верзији. Crashlytics пружа метод crash() за симулацију фаталне грешке. У јединичним тестовима проверава се исправност guard и if-let, а UI тестови покривају граничне случајеве уноса података и стања интерфејса.
Не, само необрађени изузеци постају фатални. Изузетак ухваћен try-catch-ом је non-fatal. Разлика између обрађеног и необрађеног изузетка одређује да ли ће се апликација затворити или наставити рад са алтернативним стањем уз минималну штету за корисничко искуство.
Завршни преглед
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође