Abhishek Gang Deb در این مقاله، روند بررسی یک crash در یک app مصرفی بزرگ iOS را روایت میکند؛ خطایی که فقط در بعضی اجراها رخ میداد و تلاشهای محلی توسعهدهندگان و تیم QA برای بازتولید آن نتیجه نمیداد. گزارش شامل SIGBUS و بخشهایی از Foundation مرتبط با پردازش attributed string بود، اما خط مشخصی از Swift را نشان نمیداد. SIGBUS نشانه دسترسی نامعتبر به حافظه است، نه تشخیص قطعی علت.
بررسی اولیه شامل استفاده از Zombie Objects، افزودن breakpoint و بازبینی ownership و مسیرهای اجرای غیرهمگام بود. تغییراتی در مدیریت lifecycle و synchronization نیز انجام شد. نخستین hotfix نرخ کلی crash را کاهش داد، اما همان خطای هدف همچنان در نسخه منتشرشده دیده میشد. نکته مهم این بود که تغییر زمانبندی اجرا میتواند دفعات وقوع یک خطای حساس به زمان را کم کند، بیآنکه علت اصلی برطرف شده باشد.
نقطه عطف زمانی رسید که یکی از اعضای QA توانست روی دستگاه خودش، با تکرار مسیر کاربر و گاهی پس از چهار یا پنج تلاش، خطا را بازتولید کند. از آن پس، debugging به چرخهای قابلآزمایش تبدیل شد: تغییر یک بخش، ساخت نسخه آزمایشی، نصب روی همان دستگاه و ثبت بازگشت یا عدم بازگشت crash.
نویسنده سپس بهجای اصلاح بخشهایی که مشکوک به نظر میرسیدند، هر بار یک view یا رفتار را حذف کرد. پس از چند مرحله، محدوده بررسی به یک فایل و سپس به عملیات تبدیل HTML به attributed string با NSMutableAttributedString رسید؛ فراخوانیای که در ظاهر نشانی از دسترسی ناامن به حافظه نداشت.
مقاله تأکید میکند که واردکردن HTML با NSAttributedString الزام اجرای روی main thread دارد؛ الزامی که در آمادهسازی غیرهمگام صفحه بهراحتی نادیده میماند. همچنین استفاده از یک لایه مشترک مبتنی بر MainActor را محافظی قویتر از تکیه بر یادآوری این قاعده در تکتک محلهای فراخوانی میداند.





