کرش برنامه: چیست، علل بسته شدن و روش‌های ردیابی

نویسنده: IT Sectr منتشر شده: 2026-07-27 زمان مطالعه: 7 دقیقه

کرش برنامه — پایان اضطراری که در آن برنامه از پاسخ دادن باز می‌ایستد و بسته می‌شود. در توسعه موبایل، کرش‌ها منبع اصلی نظرات منفی و کاهش رتبه هستند Firebase (2024), کاربران در ۵۳٪ موارد پس از یک یا دو کرش برنامه را حذف می‌کنند. هر بار بسته شدن میزان حفظ کاربر را ۳–۵٪ کاهش می‌دهد. سیستم‌های مانیتورینگ مانند Crashlytics و Sentry به یافتن سریع و رفع علل کرش‌ها قبل از تأثیر گسترده بر کاربران کمک می‌کنند.

نکات اصلی

  • کرش — پایان غیرمنتظره برنامه به دلیل خطای پردازش نشده زمان اجرا
  • علل اصلی — NullPointerException, OutOfMemoryError, IndexOutOfBounds, ANR در اندروید
  • Crashlytics — استاندارد مانیتورینگ کرش با جمع‌آوری خودکار stack trace و گروه‌بندی
  • Runtime exceptions — استثناهایی که کامپایلر بررسی نمی‌کند، فقط در زمان اجرا ظاهر می‌شوند
  • راهکارهای پیشگیری — نوع‌دهی قوی، binding اختیاری، مدیریت خطا و تست

کرش برنامه چیست

کرش — پایان غیرمنتظره برنامه ناشی از وضعیت استثنایی که کد آن را پردازش نکرده است. در سیستم‌عامل‌های موبایل، کرش منجر به بسته شدن فوری برنامه و نمایش صفحه «برنامه متوقف شد» یا بازگشت به صفحه اصلی می‌شود

کرش‌ها به دو دسته بزرگ تقسیم می‌شوند. خطاهای پردازش شده — بلوک‌های try/catch استثنا را می‌گیرند، برنامه به کار ادامه می‌دهد، احتمالاً با از دست دادن برخی قابلیت‌ها. کرش‌های پردازش نشده — استثنا تا سطح سیستم‌عامل بالا می‌رود و سیستم فرآیند را می‌کشد. نوع دوم بسیار خطرناک است زیرا کاربر نمی‌تواند داده‌ها را ذخیره کند.

سیستمی با دو میلیون کاربر و نرخ کرش ۰.۱٪ در هر نسخه ۲٬۰۰۰ کاربر را از دست می‌دهد. طبق Google Play Console (۲۰۲۴)، برنامه‌های با نرخ کرش بالای ۱.۵٪ از توصیه‌ها حذف می‌شوند و تا ۳۰٪ ترافیک ارگانیک را از دست می‌دهند.

علل اصلی بسته شدن در برنامه‌های موبایل

NullPointerException (NPE) — پادشاه کرش‌ها در Java/Kotlin. تلاش برای فراخوانی متد بر روی شیء null. در Kotlin به دلیل null safety کمتر رخ می‌دهد، اما همچنان با استفاده از عملگر !! یا تعامل با کد Java ممکن است. Google (2024) تخمین می‌زند: NPE ۲۵٪ از کل کرش‌های برنامه‌های Android را تشکیل می‌دهد.

IndexOutOfBoundsException — دسترسی به عنصر لیست با ایندکس ناموجود. علت رایج: داده‌ها از سرور با فرمت غیرمنتظره می‌آیند و UI سعی در نمایش موقعیتی که وجود ندارد دارد. راه‌حل — همیشه اندازه مجموعه را قبل از دسترسی با ایندکس بررسی کنید.

ANR (Application Not Responding) — مشکل خاص اندروید. رشته UI بیش از ۵ ثانیه مسدود می‌شود. علل اصلی: درخواست‌های شبکه در رشته اصلی، محاسبات سنگین، همگام‌سازی با پایگاه داده. StrictMode در اندروید به شناسایی مسدود شدن رشته UI در مرحله توسعه کمک می‌کند.

OutOfMemoryError (OOM) — برنامه از حد مجاز حافظه فراتر رفته است. در دستگاه‌های موبایل با ۲–۴ گیگابایت RAM، OOM مشکل رایج هنگام کار با تصاویر بزرگ یا لیست‌های بی‌پایان بدون صفحه‌بندی است. راه‌حل — Glide/Coil برای بارگذاری تصاویر، LruCache برای کش کردن، ViewHolder در RecyclerView.

استثناهای زمان اجرا و خطاهای مهلک

Runtime exceptions — خطاهایی که کامپایلر در مرحله ساخت بررسی نمی‌کند. آنها فقط هنگام اجرای کد روی یک دستگاه خاص با داده‌های خاص ظاهر می‌شوند. در Java اینها RuntimeException و زیرکلاس‌های آن هستند: NullPointerException, IllegalArgumentException, ArithmeticException.

خطاهای مهلک (FATAL) — نه runtime، بلکه خرابی‌های سیستمی. Signal 11 (SIGSEGV) — نقض سگمنت‌بندی حافظه در کد native. Signal 6 (SIGABRT) — پایان اضطراری که توسط خود برنامه از طریق abort() ایجاد شده است. تشخیص چنین کرش‌هایی دشوار است زیرا stack trace اغلب زمینه قابل فهمی را نشان نمی‌دهد.

در iOS علل اصلی NSInvalidArgumentException (nil غیرمنتظره در پارامتر) و EXC_BAD_ACCESS (دسترسی به حافظه آزاد شده). Swift تعداد کرش‌ها را نسبت به Objective-C کاهش داده است، اما خطاهای runtime ObjC و کتابخانه‌های C هنوز منجر به خرابی می‌شوند.

مانیتورینگ و جمع‌آوری لاگ‌های کرش

Firebase Crashlytics — استاندارد برای برنامه‌های موبایل. به طور خودکار stack trace جمع‌آوری می‌کند، لاگ‌ها، ID کاربر و متادیتای دستگاه را اضافه می‌کند. کرش‌ها را بر اساس امضا گروه‌بندی می‌کند (کلاس خطا + خط). Real-time alerts — اعلان‌هایی که وقتی نرخ کرش از آستانه مشخصی فراتر می‌رود، ارسال می‌شوند (مثلاً >۰.۱٪ در ساعت).

Sentry — جایگزینی با قابلیت‌های انعطاف‌پذیرتر. امکان ایجاد context سفارشی، افزودن breadcrumbs، پیکربندی فیلتر درون‌برنامه‌ای برای حذف خطاهای غیرمهم. Source maps برای Kotlin و Swift امکان دیدن کد منبع را فراهم می‌کنند، نه نام‌های مبهم‌سازی شده.

Best practices برای لاگ‌ها: فراداده‌های کلیدی را قبل از اجرای عملیات خطرناک ارسال کنید. Custom keys اضافه کنید (شماره نسخه API، آخرین صفحه، اندازه داده‌های ورودی). این کار stack trace بی‌فایده را به اطلاعات قابل استفاده تبدیل می‌کند.

مثال: تنظیم Crashlytics در Android

kotlin
class PaymentViewModel : ViewModel() {
    fun processPayment(amount: Double) {
        crashlytics.setCustomKey("last_screen", "payment")
        crashlytics.setCustomKey("amount", amount)
        try {
            api.charge(amount)
        } catch (e: Exception) {
            crashlytics.recordException(e)
        }
    }
}

undefined

Optional binding و null safety — در Kotlin از `?` برای انواع nullable، `let` و `?:` برای پردازش ایمن null استفاده کنید. در Swift — optionals و guard let. Modern Kotlin (2024) حاشیه‌نویسی‌های Contract را اضافه کرد: @ContractsDsl اعلام می‌کند که تابع null برنمی‌گرداند و کامپایلر آن را بررسی می‌کند.

Error handling در شبکه — هر درخواست شبکه باید timeout، خطاهای تجزیه و رد سرور را مدیریت کند. Retrofit با نوع Result — کلاس sealed که تضمین می‌کند خطا مدیریت خواهد شد. سبک No Exception: به جای try/catch از sealed Result برای مدیریت صریح موفقیت و خطا استفاده کنید.

Feature flags — قابلیت مشکل‌دار را از راه دور بدون انتشار نسخه جدید غیرفعال کنید. Firebase Remote Config امکان تغییر رفتار برنامه بدون انتشار در فروشگاه را فراهم می‌کند.

انتشار تدریجی — نسخه جدید را برای ۵٪ مخاطب منتشر کنید و نرخ کرش را نظارت کنید. اگر نرخ زیر هدف باقی ماند، به ۲۵٪، سپس ۵۰٪، سپس ۱۰۰٪ گسترش دهید. Google Play Console و App Store Connect از انتشار مرحله‌ای برای توقف خودکار هنگام فراتر رفتن از آستانه پشتیبانی می‌کنند.

برنامه اقدام در صورت کشف خطا

1: طبقه‌بندی — severity را تعیین کنید: Critical (کرش در >۱٪ کاربران)، High (۰.۱–۱٪)، Medium (<۰.۱٪). برای کرش‌های Critical — پاسخ فوری. Google Play Console به طور خودکار کرش‌ها را بر اساس تعداد کاربران آسیب‌دیده طبقه‌بندی می‌کند.

2: تحلیل stack trace — لاگ را در Crashlytics باز کنید، مکان دقیق خرابی را ببینید. Custom keys را بررسی کنید: کدام صفحه، چه داده‌هایی، نسخه سیستم‌عامل. با آخرین استقرار مقایسه کنید — اغلب کرش ناشی از تغییر جدید در کد است که بر سناریوی استفاده غیرمنتظره تأثیر گذاشته است.

3: بازتولید — سعی کنید کرش را روی دستگاه یا شبیه‌ساز با پارامترهای مشابه بازتولید کنید. اگر موفق نشدید، لاگ کرش را برای الگوها بررسی کنید: مدل‌های خاص (Samsung A10)، نسخه‌های Android (API < 26)، locale. راه‌حل — یک شرط محافظتی اضافه کنید که سناریو را پوشش می‌دهد.

4: رفع و نظارت — hotfix را با اولویت منتشر کنید. پس از انتشار مطمئن شوید که نرخ کرش برای این نوع به صفر می‌رسد. تست رگرسیون بنویسید که سناریوی کرش را پوشش می‌دهد. بدون تست، همان باگ ممکن است در بازسازی بعدی بازگردد.

سوالات متداول

چه نرخ کرشی نرمال محسوب می‌شود؟

نرخ کرش نرمال — کمتر از ۰.۱٪ برای انتشارات تولیدی. Google Play توصیه می‌کند نرخ کرش را زیر ۱.۵٪ نگه دارید، اما برنامه‌های برتر (YouTube, Instagram) نرخ ۰.۰۱–۰.۰۵٪ را حفظ می‌کنند. برای انتشار قابلیت جدید، افزایش موقت تا ۰.۵٪ با کاهش بعدی پس از hotfix مجاز است.

کرش چه تفاوتی با ANR دارد؟

کرش — برنامه به طور اضطراری خاتمه می‌یابد. ANR (Application Not Responding) — برنامه بیش از ۵ ثانیه قفل می‌کند، اما به زور بسته نمی‌شود. کاربر دیالوگ «برنامه پاسخ نمی‌دهد» را می‌بیند و می‌تواند صبر کند یا ببندد. مشکلات ANR کمتر از کرش‌ها جدی نیستند و همچنین بر رتبه فروشگاه تأثیر می‌گذارند.

چرا کرش ممکن است در همه دستگاه‌ها تکرار نشود؟

دستگاه‌های مختلف نسخه‌های متفاوت سیستم‌عامل، میزان حافظه، نسخه کتابخانه‌ها و حتی پردازنده‌های مختلف دارند. مثال: کرش در Android 6 (API 23) به دلیل فقدان مجوز زمان اجرا ممکن است در Android 12 تکرار نشود.

اگر stack trace اطلاعات مفیدی نداشته باشد، چگونه علت کرش را پیدا کنیم؟

Custom breadcrumbs در Crashlytics اضافه کنید: رویدادهای کلیدی را قبل از اجرای عملیات ثبت کنید. Debug symbols (dSYM, ProGuard mapping) — حتماً به Crashlytics آپلود کنید تا نام واقعی توابع را ببینید، نه نام‌های مبهم‌سازی شده.

آیا در خطاهای غیرمهلک باید برنامه را کرش کرد؟

در تولید — هرگز. کرش‌های پردازش نشده تجربه کاربری را بدتر می‌کند. از try/catch با ثبت خطا استفاده کنید. در حالت debug کرش کردن برای بازخورد سریع به توسعه‌دهنده مجاز است. Assertions — برای بررسی تغییرناپذیرهایی که هرگز نباید نقض شوند، اما فقط در بیلدهای debug.

خلاصه

  • کرش — پایان اضطراری برنامه که منجر به از دست دادن کاربران و کاهش رتبه در فروشگاه‌ها می‌شود
  • NullPointerException — شایع‌ترین علت کرش در برنامه‌های موبایل (۲۵٪ از کل خرابی‌ها)
  • ANR و OOM — مشکلات بحرانی خاص اندروید که نیاز به مانیتورینگ و پیشگیری جداگانه دارند
  • Crashlytics و Sentry — ابزارهای اصلی جمع‌آوری stack trace با گروه‌بندی و اعلان‌های بلادرنگ
  • Error handling — optional binding، انواع sealed Result و بررسی‌های محافظتی از اکثر کرش‌ها جلوگیری می‌کنند
  • Feature flags و staged rollout — تأثیر باگ‌ها را بر مخاطب کاهش می‌دهند و امکان بازگشت کد مشکل‌دار را فراهم می‌کنند
  • پس از رفع کرش تست رگرسیون برای جلوگیری از عود مشکل اجباری است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید