Z 您現(xiàn)在的位置:首頁>產(chǎn)業(yè)專欄>國內(nèi)資訊> 技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

2015-04-30 14:57:04來源:優(yōu)游網(wǎng)發(fā)布:優(yōu)游網(wǎng)

作為玩家,當(dāng)游戲crash的時(shí)候是什么心情,如果這個(gè)游戲玩起來還不錯(cuò)的話,那我可能還會(huì)打開第二次,如果這個(gè)游戲一般的話我可能直接怒刪了。當(dāng)多次出現(xiàn)閃退crash的時(shí)候,這種糟糕的體驗(yàn)很容易讓用戶流失,造成很大的損失。但是作為測(cè)試人員,面對(duì)如此棘手的事情,首先要做的是協(xié)助開發(fā)組解決問題。沒錯(cuò),第一件要做的事情就是去定位crash發(fā)生的代碼邏輯,到底是哪個(gè)文件的哪一段函數(shù)邏輯導(dǎo)致了這個(gè)crash問題。因此,我們需要去盡量重現(xiàn)crash場(chǎng)景,收集解析crash日志,以此定位到具體到游戲代碼邏輯中尋找導(dǎo)致crash的原因,改善項(xiàng)目的質(zhì)量和體驗(yàn)。本文闡述在App crash產(chǎn)生的原理,收集和解析過程,旨在經(jīng)驗(yàn)積累,與大家分享。

一.crash產(chǎn)生的原因

當(dāng)iOS/Android設(shè)備上的App應(yīng)用閃退時(shí),操作系統(tǒng)會(huì)生成一個(gè)crash日志,保存在設(shè)備上。crash日志上有很多有用的信息,比如每個(gè)正在執(zhí)行線程的完整堆棧跟蹤信息和內(nèi)存映像,這樣就能夠通過解析這些信息進(jìn)而定位crash發(fā)生時(shí)的代碼邏輯,從而找到App閃退的原因。通常來說,crash產(chǎn)生來源于兩種問題:違反iOS系統(tǒng)規(guī)則導(dǎo)致的crash和App代碼邏輯BUG導(dǎo)致的crash,下面分別對(duì)他們進(jìn)行分析。

1.1違反iOS系統(tǒng)規(guī)則包括三種類型:

(1) 內(nèi)存報(bào)警閃退

當(dāng)iOS檢測(cè)到內(nèi)存過低時(shí),它的VM系統(tǒng)會(huì)發(fā)出低內(nèi)存警告通知,嘗試回收一些內(nèi)存;如果情況沒有得到足夠的改善,iOS會(huì)終止后臺(tái)應(yīng)用以回收更多內(nèi)存;最后,如果內(nèi)存還是不足,那么正在運(yùn)行的應(yīng)用可能會(huì)被終止掉。在Debug模式下,可以主動(dòng)將客戶端執(zhí)行的動(dòng)作邏輯寫入一個(gè)log文件中,這樣程序童鞋可以將內(nèi)存預(yù)警的邏輯寫入該log文件,當(dāng)發(fā)生如下截圖中的內(nèi)存報(bào)警時(shí),就是提醒當(dāng)前客戶端性能內(nèi)存吃緊,可以通過Instruments工具中的Allocations 和 Leaks模塊庫來發(fā)現(xiàn)內(nèi)存分配問題和內(nèi)存泄漏問題。

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

(2) 響應(yīng)超時(shí)

當(dāng)應(yīng)用程序?qū)σ恍┨囟ǖ氖录?比如啟動(dòng)、掛起、恢復(fù)、結(jié)束)響應(yīng)不及時(shí),蘋果的Watchdog機(jī)制會(huì)把應(yīng)用程序干掉,并生成一份相應(yīng)的crash日志。這些事件與下列UIApplicationDelegate方法相對(duì)應(yīng),當(dāng)遇到Watchdog日志時(shí),可以檢查上圖中的幾個(gè)方法是否有比較重的阻塞UI的動(dòng)作。

application:didFinishLaunchingWithOptions:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationDidBecomeActive:

applicationWillTerminate:

(3) 用戶強(qiáng)制退出

一看到“用戶強(qiáng)制退出”,首先可能想到的雙擊Home鍵,然后關(guān)閉應(yīng)用程序。不過這種場(chǎng)景一般是不會(huì)產(chǎn)生crash日志的,因?yàn)殡p擊Home鍵后,所有的應(yīng)用程序都處于后臺(tái)狀態(tài),而iOS隨時(shí)都有可能關(guān)閉后臺(tái)進(jìn)程,當(dāng)應(yīng)用阻塞界面并停止響應(yīng)時(shí)這種場(chǎng)景才會(huì)產(chǎn)生crash日志。

這里指的“用戶強(qiáng)制退出”場(chǎng)景,是稍微比較復(fù)雜點(diǎn)的操作:先按住電源鍵,直到出現(xiàn)“滑動(dòng)關(guān)機(jī)”的界面時(shí),再按住Home鍵,這時(shí)候當(dāng)前應(yīng)用程序會(huì)被終止掉,并且產(chǎn)生一份相應(yīng)事件的crash日志。

1.2應(yīng)用邏輯的Bug

大多數(shù)閃退崩潰日志的產(chǎn)生都是因?yàn)閼?yīng)用中的Bug,這種Bug的錯(cuò)誤種類有很多,比如

SEGV:(Segmentation Violation,段違例),無效內(nèi)存地址,比如空指針,未初始化指針,棧溢出等;

SIGABRT:收到Abort信號(hào),可能自身調(diào)用abort()或者收到外部發(fā)送過來的信號(hào);

SIGBUS:總線錯(cuò)誤。與SIGSEGV不同的是,SIGSEGV訪問的是無效地址(比如虛存映射不到物理內(nèi)存),而SIGBUS訪問的是有效地址,但總線訪問異常(比如地址對(duì)齊問題);

SIGILL:嘗試執(zhí)行非法的指令,可能不被識(shí)別或者沒有權(quán)限;

SIGFPE:Floating Point Error,數(shù)學(xué)計(jì)算相關(guān)問題(可能不限于浮點(diǎn)計(jì)算),比如除零操作;

SIGPIPE:管道另一端沒有進(jìn)程接手?jǐn)?shù)據(jù);

常見的崩潰原因基本都是代碼邏輯問題或資源問題,比如數(shù)組越界,訪問野指針或者美術(shù)資源不存在,或美術(shù)資源大小寫錯(cuò)誤等,這種問題的類型有很多,不再詳細(xì)介紹。

二.crash的收集

上文提到crash日志是操作系統(tǒng)層產(chǎn)生并保存在設(shè)備上的,那如果我的一臺(tái)設(shè)備在運(yùn)行某App的時(shí)候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)出來,然后再單獨(dú)對(duì)這個(gè)crash文件做處理分析。

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

以上這些是針對(duì)能夠拿到真機(jī)設(shè)備的情況下才能收集crash日志的。如果是針對(duì)玩家的話,當(dāng)App在玩家的設(shè)備上crash的時(shí)候如何收集呢。先來看下市場(chǎng)上已有的商業(yè)軟件提供crash收集服務(wù),他們這些軟件基本都提供了日志存儲(chǔ),日志符號(hào)化解析和服務(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)缺點(diǎn),有人做了如下統(tǒng)計(jì):

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

除了上述所說的這些商業(yè)軟件外,還有一些開源的軟件也可以拿來收集crash日志,比如Razor,QuincyKit(git鏈接)等,這些軟件收集crash的原理其實(shí)大同小異,都是根據(jù)系統(tǒng)產(chǎn)生的crash日志進(jìn)行了一次提取或封裝,然后將封裝后的crash文件上傳到對(duì)應(yīng)的服務(wù)端進(jìn)行解析處理。很多商業(yè)軟件都采用了Plcrashreporter這個(gè)開源工具來上傳和解析crash,比如HockeyApp,Flurry和crittercism等,下圖是筆者利用這一開源框架制作的一個(gè)收集crash的樣例。

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

通過這種方式就可以很好的支持開發(fā)人員收集crash日志的需求,進(jìn)而定位和解決App產(chǎn)品存在的問題。如果有需要或者感興趣的可以深入的調(diào)研一下。

但是有個(gè)很重要的問題就是這種方式只能收集游戲引擎層(c++或object c代碼)的邏輯,如果是腳本邏輯問題產(chǎn)生的crash就無能無力了。而現(xiàn)在手游項(xiàng)目基本都是引擎(cocos2dx或Neox)+腳本(lua或javascript)的開發(fā)模式,幾乎所有的業(yè)務(wù)邏輯都在腳本層,游戲App時(shí)常發(fā)生的crash幾乎都是由腳本邏輯bug導(dǎo)致的,這該怎么處理呢?平時(shí)在開發(fā)階段,程序童鞋在Debug模式下開通了客戶端運(yùn)行日志功能,當(dāng)出現(xiàn)crash或者traceback等問題的時(shí)候直接去查看log文件的輸出即可知道原因了,但是在Release模式下一切l(wèi)og輸出均被屏蔽,邏輯運(yùn)行的log消息輸出也就無法查看了。這種情況該又該如何處理呢?方法總比問題多,iOS/Android系統(tǒng)提供了異常發(fā)生時(shí)的處理API,只需要在程序啟動(dòng)的地方加入對(duì)應(yīng)的處理邏輯,當(dāng)異常發(fā)生時(shí)就可以觸發(fā)對(duì)應(yīng)的回調(diào)函數(shù)將必要的信息進(jìn)行處理上傳,適時(shí)地反饋給開發(fā)組。比如,下圖是某項(xiàng)目組在iOS平臺(tái)收集crash的一個(gè)截圖:

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

其實(shí),它具體的實(shí)現(xiàn)原理是這樣的:首先,在游戲應(yīng)用程序啟動(dòng)的地方需要開啟異常處理邏輯的handler:

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

最后需要當(dāng)crash發(fā)生時(shí),需要調(diào)用的回調(diào)函數(shù)處理具體如下:

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

這樣在當(dāng)玩家在Release游戲版本中出現(xiàn)邏輯異常導(dǎo)致crash時(shí),就會(huì)把對(duì)應(yīng)的腳本層的異常(traceback或error等)以類似dump文件的形式發(fā)送到指定的服務(wù)端,方便運(yùn)營維護(hù)人員進(jìn)行快速定位分析。這些腳本層異常日志收集后的顯示效果如下:

以具體某一個(gè)異常日志文件為例,具體上傳的內(nèi)容如下圖。這是一種直接可讀的文本,里面記錄著crash發(fā)生時(shí)代碼邏輯的traceback,通過閱讀代碼邏輯就可以直接定位到或推斷導(dǎo)致crash

技術(shù)貼:手游頻繁崩潰”閃退”的原因是什么?

以上就是收集crash的方法和原理,通過這種方式收集到crash日志后接下來就可以具體根據(jù)日志的內(nèi)容進(jìn)行解析來定位到底是什么原因?qū)е碌腸rash。

最新禮包
熱門手游榜
1 王者榮耀
王者榮耀

手機(jī)網(wǎng)游

下載

2 陰陽師
陰陽師

角色養(yǎng)成

下載

4 明日之后
明日之后

動(dòng)作冒險(xiǎn)

下載

5 一起來捉妖
一起來捉妖

角色養(yǎng)成

下載

8 奇跡暖暖
奇跡暖暖

角色養(yǎng)成

下載

9 少年歌行
少年歌行

角色養(yǎng)成

下載

優(yōu)游網(wǎng)訂閱號(hào)