技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?
2015-04-30 14:57:04來源:優(yōu)游網(wǎng)發(fā)布:優(yōu)游網(wǎng)
作為玩家,當(dāng)游戲crash的時候是什么心情,如果這個游戲玩起來還不錯的話,那我可能還會打開第二次,如果這個游戲一般的話我可能直接怒刪了。當(dāng)多次出現(xiàn)閃退crash的時候,這種糟糕的體驗很容易讓用戶流失,造成很大的損失。但是作為測試人員,面對如此棘手的事情,首先要做的是協(xié)助開發(fā)組解決問題。沒錯,第一件要做的事情就是去定位crash發(fā)生的代碼邏輯,到底是哪個文件的哪一段函數(shù)邏輯導(dǎo)致了這個crash問題。因此,我們需要去盡量重現(xiàn)crash場景,收集解析crash日志,以此定位到具體到游戲代碼邏輯中尋找導(dǎo)致crash的原因,改善項目的質(zhì)量和體驗。本文闡述在App crash產(chǎn)生的原理,收集和解析過程,旨在經(jīng)驗積累,與大家分享。
一.crash產(chǎn)生的原因
當(dāng)iOS/Android設(shè)備上的App應(yīng)用閃退時,操作系統(tǒng)會生成一個crash日志,保存在設(shè)備上。crash日志上有很多有用的信息,比如每個正在執(zhí)行線程的完整堆棧跟蹤信息和內(nèi)存映像,這樣就能夠通過解析這些信息進(jìn)而定位crash發(fā)生時的代碼邏輯,從而找到App閃退的原因。通常來說,crash產(chǎn)生來源于兩種問題:違反iOS系統(tǒng)規(guī)則導(dǎo)致的crash和App代碼邏輯BUG導(dǎo)致的crash,下面分別對他們進(jìn)行分析。
1.1違反iOS系統(tǒng)規(guī)則包括三種類型:
(1) 內(nèi)存報警閃退
當(dāng)iOS檢測到內(nèi)存過低時,它的VM系統(tǒng)會發(fā)出低內(nèi)存警告通知,嘗試回收一些內(nèi)存;如果情況沒有得到足夠的改善,iOS會終止后臺應(yīng)用以回收更多內(nèi)存;最后,如果內(nèi)存還是不足,那么正在運行的應(yīng)用可能會被終止掉。在Debug模式下,可以主動將客戶端執(zhí)行的動作邏輯寫入一個log文件中,這樣程序童鞋可以將內(nèi)存預(yù)警的邏輯寫入該log文件,當(dāng)發(fā)生如下截圖中的內(nèi)存報警時,就是提醒當(dāng)前客戶端性能內(nèi)存吃緊,可以通過Instruments工具中的Allocations 和 Leaks模塊庫來發(fā)現(xiàn)內(nèi)存分配問題和內(nèi)存泄漏問題。
(2) 響應(yīng)超時
當(dāng)應(yīng)用程序?qū)σ恍┨囟ǖ氖录?比如啟動、掛起、恢復(fù)、結(jié)束)響應(yīng)不及時,蘋果的Watchdog機(jī)制會把應(yīng)用程序干掉,并生成一份相應(yīng)的crash日志。這些事件與下列UIApplicationDelegate方法相對應(yīng),當(dāng)遇到Watchdog日志時,可以檢查上圖中的幾個方法是否有比較重的阻塞UI的動作。
application:didFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationDidBecomeActive:
applicationWillTerminate:
(3) 用戶強(qiáng)制退出
一看到“用戶強(qiáng)制退出”,首先可能想到的雙擊Home鍵,然后關(guān)閉應(yīng)用程序。不過這種場景一般是不會產(chǎn)生crash日志的,因為雙擊Home鍵后,所有的應(yīng)用程序都處于后臺狀態(tài),而iOS隨時都有可能關(guān)閉后臺進(jìn)程,當(dāng)應(yīng)用阻塞界面并停止響應(yīng)時這種場景才會產(chǎn)生crash日志。
這里指的“用戶強(qiáng)制退出”場景,是稍微比較復(fù)雜點的操作:先按住電源鍵,直到出現(xiàn)“滑動關(guān)機(jī)”的界面時,再按住Home鍵,這時候當(dāng)前應(yīng)用程序會被終止掉,并且產(chǎn)生一份相應(yīng)事件的crash日志。
1.2應(yīng)用邏輯的Bug
大多數(shù)閃退崩潰日志的產(chǎn)生都是因為應(yīng)用中的Bug,這種Bug的錯誤種類有很多,比如
SEGV:(Segmentation Violation,段違例),無效內(nèi)存地址,比如空指針,未初始化指針,棧溢出等;
SIGABRT:收到Abort信號,可能自身調(diào)用abort()或者收到外部發(fā)送過來的信號;
SIGBUS:總線錯誤。與SIGSEGV不同的是,SIGSEGV訪問的是無效地址(比如虛存映射不到物理內(nèi)存),而SIGBUS訪問的是有效地址,但總線訪問異常(比如地址對齊問題);
SIGILL:嘗試執(zhí)行非法的指令,可能不被識別或者沒有權(quán)限;
SIGFPE:Floating Point Error,數(shù)學(xué)計算相關(guān)問題(可能不限于浮點計算),比如除零操作;
SIGPIPE:管道另一端沒有進(jìn)程接手?jǐn)?shù)據(jù);
常見的崩潰原因基本都是代碼邏輯問題或資源問題,比如數(shù)組越界,訪問野指針或者美術(shù)資源不存在,或美術(shù)資源大小寫錯誤等,這種問題的類型有很多,不再詳細(xì)介紹。
二.crash的收集
上文提到crash日志是操作系統(tǒng)層產(chǎn)生并保存在設(shè)備上的,那如果我的一臺設(shè)備在運行某App的時候crash了,可以通過什么方式拿到crash日志呢。如果是在windows上你可以通過itools或pp助手等輔助工具查看系統(tǒng)產(chǎn)生的歷史crash日志,然后再根據(jù)app來查看。如果是在Mac 系統(tǒng)上,只需要打開xcode->windows->organizer->devices,選擇device logs進(jìn)行查看,如下圖,這些crash文件都可以導(dǎo)出來,然后再單獨對這個crash文件做處理分析。
以上這些是針對能夠拿到真機(jī)設(shè)備的情況下才能收集crash日志的。如果是針對玩家的話,當(dāng)App在玩家的設(shè)備上crash的時候如何收集呢。先來看下市場上已有的商業(yè)軟件提供crash收集服務(wù),他們這些軟件基本都提供了日志存儲,日志符號化解析和服務(wù)端可視化管理等服務(wù):
Crashlytics (www.crashlytics.com)
Crittercism (www.crittercism.com)
Bugsense (www.bugsense.com)
TestFlight (www.testflightapp.com)
HockeyApp (www.hockeyapp.net)
Flurry(www.flurry.com)
具體這些商業(yè)軟件有哪些優(yōu)缺點,有人做了如下統(tǒng)計:
除了上述所說的這些商業(yè)軟件外,還有一些開源的軟件也可以拿來收集crash日志,比如Razor,QuincyKit(git鏈接)等,這些軟件收集crash的原理其實大同小異,都是根據(jù)系統(tǒng)產(chǎn)生的crash日志進(jìn)行了一次提取或封裝,然后將封裝后的crash文件上傳到對應(yīng)的服務(wù)端進(jìn)行解析處理。很多商業(yè)軟件都采用了Plcrashreporter這個開源工具來上傳和解析crash,比如HockeyApp,Flurry和crittercism等,下圖是筆者利用這一開源框架制作的一個收集crash的樣例。
通過這種方式就可以很好的支持開發(fā)人員收集crash日志的需求,進(jìn)而定位和解決App產(chǎn)品存在的問題。如果有需要或者感興趣的可以深入的調(diào)研一下。
但是有個很重要的問題就是這種方式只能收集游戲引擎層(c++或object c代碼)的邏輯,如果是腳本邏輯問題產(chǎn)生的crash就無能無力了。而現(xiàn)在手游項目基本都是引擎(cocos2dx或Neox)+腳本(lua或javascript)的開發(fā)模式,幾乎所有的業(yè)務(wù)邏輯都在腳本層,游戲App時常發(fā)生的crash幾乎都是由腳本邏輯bug導(dǎo)致的,這該怎么處理呢?平時在開發(fā)階段,程序童鞋在Debug模式下開通了客戶端運行日志功能,當(dāng)出現(xiàn)crash或者traceback等問題的時候直接去查看log文件的輸出即可知道原因了,但是在Release模式下一切l(wèi)og輸出均被屏蔽,邏輯運行的log消息輸出也就無法查看了。這種情況該又該如何處理呢?方法總比問題多,iOS/Android系統(tǒng)提供了異常發(fā)生時的處理API,只需要在程序啟動的地方加入對應(yīng)的處理邏輯,當(dāng)異常發(fā)生時就可以觸發(fā)對應(yīng)的回調(diào)函數(shù)將必要的信息進(jìn)行處理上傳,適時地反饋給開發(fā)組。比如,下圖是某項目組在iOS平臺收集crash的一個截圖:
其實,它具體的實現(xiàn)原理是這樣的:首先,在游戲應(yīng)用程序啟動的地方需要開啟異常處理邏輯的handler:
最后需要當(dāng)crash發(fā)生時,需要調(diào)用的回調(diào)函數(shù)處理具體如下:
這樣在當(dāng)玩家在Release游戲版本中出現(xiàn)邏輯異常導(dǎo)致crash時,就會把對應(yīng)的腳本層的異常(traceback或error等)以類似dump文件的形式發(fā)送到指定的服務(wù)端,方便運營維護(hù)人員進(jìn)行快速定位分析。這些腳本層異常日志收集后的顯示效果如下:
以具體某一個異常日志文件為例,具體上傳的內(nèi)容如下圖。這是一種直接可讀的文本,里面記錄著crash發(fā)生時代碼邏輯的traceback,通過閱讀代碼邏輯就可以直接定位到或推斷導(dǎo)致crash
以上就是收集crash的方法和原理,通過這種方式收集到crash日志后接下來就可以具體根據(jù)日志的內(nèi)容進(jìn)行解析來定位到底是什么原因?qū)е碌腸rash。
相關(guān)閱讀
- 04-30 ·彈射型手游《喧嘩番長-Crash Battle-》iOS版于日本推出
- 04-30 ·狂熱崩壞手游無法聯(lián)機(jī)怎么辦 無法聯(lián)機(jī)解決方案
- 04-30 ·崩潰大陸Crashlands犀牛怪打法攻略
- 04-30 ·崩潰大陸Crashlands給寵物喂食詳解
- 04-30 ·崩潰大陸Crashlands石器工作臺怎么解鎖
- 04-30 ·崩潰大陸Crashlands鋤頭怎么獲取
- 04-30 ·崩潰大陸Crashlands第二個boss打法攻略
- 04-30 ·崩潰大陸Crashlands太陽花獲取攻略
- 04-30 ·崩潰大陸Crashlands第一個boss攻略
- 04-30 ·崩潰大陸Crashlands前期開局攻略