欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

os_object_release Crash 排查記錄分析

 更新時(shí)間:2022年11月30日 11:02:26   作者:波兒菜  
這篇文章主要為大家介紹了os_object_release Crash 排查記錄分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Crash 信息

線上存在一個(gè)持續(xù)很久的 Crash,由于沒(méi)有明確業(yè)務(wù)棧且量級(jí)不算大,讓它成為了老賴之一,Crash 棧是這樣的:

Thread 55
0  libdispatch.dylib              0x0000000188a8cf8c __os_object_release_internal_n +  80
1  libdispatch.dylib              0x0000000188a96eec __dispatch_lane_invoke +  1152
2  libdispatch.dylib              0x0000000188aa14bc __dispatch_workloop_worker_thread +  764
3  libsystem_pthread.dylib        0x00000001d4bde7a4 __pthread_wqthread +  276
——-
Exception Type: SIGTRAP 
Exception Codes: fault addr: 0x0000000188a8cf8c
Crashed Thread: 55 
Thread 55 crashed with ARM Thread State (64-bit):
    x0:0x0000000281a86580    x1:0x0000000000000002
0x188a8a000 - 0x188acefff  arm64 <ff408738d75b3061ad994a929c0162d2> libdispatch.dylib

由于不能明確是哪個(gè)業(yè)務(wù)代碼引起的,所以先確認(rèn) Crash 的對(duì)象是哪個(gè)類型。

確認(rèn)目標(biāo)對(duì)象類型

Crash 日志看不出來(lái)目標(biāo)對(duì)象類型,只知道是一個(gè) SIGTRAP,應(yīng)該是 GCD 調(diào)用__builtin_trap()觸發(fā)軟中斷結(jié)束進(jìn)程 ,嘗試從源碼入手,頂層函數(shù)邏輯是這樣的:

DISPATCH_NOINLINE
void _os_object_release_internal_n(_os_object_t obj, uint16_t n) {
	return _os_object_release_internal_n_inline(obj, n);
}
DISPATCH_ALWAYS_INLINE
static inline void _os_object_release_internal_n_inline(_os_object_t obj, int n)
{
	int ref_cnt = _os_object_refcnt_sub(obj, n);
	if (likely(ref_cnt >= 0)) {
		return;
	}
	if (unlikely(ref_cnt < -1)) {
		_OS_OBJECT_CLIENT_CRASH("Over-release of an object");
	}
	// _os_object_refcnt_dispose_barrier() is in _os_object_dispose()
	return _os_object_dispose(obj);
}

_OS_OBJECT_CLIENT_CRASH()就是調(diào)用的__builtin_trap(),那確認(rèn)就是一個(gè)os_object_t對(duì)象的 Over-Release 問(wèn)題了。os_object_t定義是這樣的:

typedef struct _os_object_s {
	_OS_OBJECT_HEADER(
	const _os_object_vtable_s *os_obj_isa,
	os_obj_ref_cnt,
	os_obj_xref_cnt);
} _os_object_s;
typedef struct _os_object_s *_os_object_t;

這就是 GCD 類的結(jié)構(gòu)體定義,和 NSObject 類似的內(nèi)存布局,但os_object_t衍生類眾多還需明確是哪一個(gè)。

繼續(xù)看上一個(gè)函數(shù)_dispatch_lane_invoke,發(fā)現(xiàn)它的代碼量很大,且由于 GCD 大量的 inline 函數(shù),很難確定是哪里調(diào)用了_os_object_release_internal_n。這個(gè)時(shí)候就要換一種方式,直接反匯編就能快速確認(rèn)。

使用和 Crash 棧相同系統(tǒng)設(shè)備切 release 環(huán)境運(yùn)行,但有點(diǎn)奇怪的是反匯編代碼和_dispatch_lane_invoke偏移對(duì)不上。那就用 hopper 直接打開(kāi) uuid 對(duì)應(yīng)的 libdispatch.dylib 可執(zhí)行文件吧,找到偏移處:

接下來(lái)就要確認(rèn)bl _os_object_release_internal_n時(shí)x0寄存器值怎么來(lái)的,這個(gè)函數(shù)一千多行指令分析工作量太大,但這里可以明確的是這個(gè)函數(shù)只有這一處調(diào)用 _os_object_release_internal_n。

那又回到 GCD 源碼,估計(jì)就是尾部的一個(gè)調(diào)用了(代碼有修改,去除無(wú)用代碼和 inline 調(diào)用):

_dispatch_lane_invoke(…) {
	dispatch_queue_t dq = dqu._dq;
	…
	return _os_object_release_internal_n(dou._os_obj, 2);
}

翻了一下各個(gè) Crash 日志x1寄存器都是 2 可以對(duì)得上。同時(shí)運(yùn)行時(shí)反匯編指令雖然對(duì)不上,但對(duì)比找到同樣邏輯的匯編代碼段,br到這個(gè)偏移也能確認(rèn)x0就是dispatch_queue_t

定位 Crash 場(chǎng)景

既然產(chǎn)生 Over-Release 的對(duì)象是 dispatch_queue_t,那推測(cè)就是業(yè)務(wù)代碼使用時(shí)存在內(nèi)存管理問(wèn)題,最蠢的方式就是找到所有的dispatch_queue_create()調(diào)用排查各個(gè)場(chǎng)景是否有問(wèn)題。

不過(guò)在這之前可以多看一下 Crash 日志,調(diào)用棧有dispatch_workloop_worker_thread可以推測(cè)當(dāng)前時(shí)機(jī)是業(yè)務(wù)block加入了 GCD 隊(duì)列,現(xiàn)在已經(jīng)開(kāi)始調(diào)度了。舉個(gè)例子,如果在dispatch_async(queue, block)時(shí) queue 就已經(jīng)釋放了,那 Crash 棧就會(huì)有dispatch_async,說(shuō)明在調(diào)用dispatch_async(queue, block)時(shí) queue 是正常的,在調(diào)度過(guò)程要結(jié)束時(shí) queue 才被其它線程釋放,立即走到_dispatch_lane_invoke的尾調(diào)用時(shí)才觸發(fā)了 Over-Release。

那其它線程引起 queue 釋放的時(shí)機(jī)和當(dāng)前 Crash 時(shí)機(jī)應(yīng)該很近,也就是說(shuō)其它線程此時(shí)的堆棧大概率有釋放這個(gè)dispatch_queue_t的調(diào)用,排查后發(fā)現(xiàn)基本上在另外一個(gè)線程都有這么一段調(diào)用棧:

9  libdispatch.dylib              0x0000000188a8dfc0 -[OS_dispatch_queue _xref_dispose] +  56
10 AnyProject                       0x0000000107c9b724 -[AnySDKClass dealloc] +  164
11 AnyProject                        0x0000000107cbc10c -[AnySDKClass .cxx_destruct] +  76

那大概率問(wèn)題就出在AnySDKClass,運(yùn)行時(shí)找到其dealloc方法:

…
    0x107ddab88 <+124>: bl     0x109994540               ; symbol stub for: dispatch_sync
    0x107ddab8c <+128>: add    x0, x19, #0x10            ; =0x10 
    0x107ddab90 <+132>: mov    x1, #0x0
    0x107ddab94 <+136>: bl     0x10999589c               ; symbol stub for: objc_storeWeak
    0x107ddab98 <+140>: ldr    x0, [x19, #0x18]
    0x107ddab9c <+144>: str    xzr, [x19, #0x18]
    0x107ddaba0 <+148>: bl     0x1099957e8               ; symbol stub for: objc_release
    0x107ddaba4 <+152>: ldr    x0, [x19, #0x58]
    0x107ddaba8 <+156>: str    xzr, [x19, #0x58]
    0x107ddabac <+160>: bl     0x1099957e8               ; symbol stub for: objc_release
…

斷點(diǎn)到對(duì)應(yīng)偏移0x107ddabac處,找到這個(gè) queue 的類型:

br set -a 0x107ddabac
po $x0
<OS_dispatch_queue_serial: anyName[0x2809e2900] = { xref = 1, ref = 1, sref = 1, target = com.apple.root.default-qos.overcommit[0x12e435100], width = 0x1, state = 0x001ffe2000000000, in-flight = 0}>

那剩下的工作就是找到對(duì)應(yīng) SDK 源碼,分析出這個(gè) serial queue 的內(nèi)存管理問(wèn)題了。

以上就是os_object_release Crash 排查記錄分析的詳細(xì)內(nèi)容,更多關(guān)于os_object_release Crash排查的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 匯編語(yǔ)言:x86匯編指令大全及其注意事項(xiàng)

    匯編語(yǔ)言:x86匯編指令大全及其注意事項(xiàng)

    用最精煉的語(yǔ)言,記錄匯編語(yǔ)言中所有常用或不常用或極其重要的匯編指令及其注意事項(xiàng),以方便自己和讀者進(jìn)行查閱,如有錯(cuò)誤和不足請(qǐng)?jiān)谠u(píng)論區(qū)指出
    2021-10-10
  • 匯編語(yǔ)言指令集學(xué)習(xí)條件轉(zhuǎn)移指令詳解

    匯編語(yǔ)言指令集學(xué)習(xí)條件轉(zhuǎn)移指令詳解

    這篇文章主要為大家介紹了匯編語(yǔ)言指令集學(xué)習(xí)條件轉(zhuǎn)移的指令全面總結(jié)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • 匯編程序成績(jī)排序的實(shí)現(xiàn)

    匯編程序成績(jī)排序的實(shí)現(xiàn)

    這篇文章主要介紹了匯編程序成績(jī)排序的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 匯編實(shí)現(xiàn)的memcpy和memset的方法

    匯編實(shí)現(xiàn)的memcpy和memset的方法

    這篇文章主要介紹了匯編實(shí)現(xiàn)的memcpy和memset的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 8086匯編語(yǔ)言nasm版本

    8086匯編語(yǔ)言nasm版本

    這篇文章主要介紹了8086匯編語(yǔ)言nasm版本,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 用匯編語(yǔ)言實(shí)現(xiàn)從1加到100的方法(1+2+...+100)

    用匯編語(yǔ)言實(shí)現(xiàn)從1加到100的方法(1+2+...+100)

    這篇文章主要介紹了用匯編語(yǔ)言實(shí)現(xiàn)從1加到100的方法(1+2+...+100),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 匯編語(yǔ)言loop命令的具體使用

    匯編語(yǔ)言loop命令的具體使用

    LOOP指令是根據(jù)ECX計(jì)數(shù)器循環(huán),將語(yǔ)句塊重復(fù)執(zhí)行特定次數(shù),本文主要介紹了匯編語(yǔ)言loop命令的具體使用,感興趣的可以了解一下
    2024-03-03
  • 匯編語(yǔ)言mov指令及基本用法

    匯編語(yǔ)言mov指令及基本用法

    在匯編語(yǔ)言中,MOV指令是數(shù)據(jù)傳送指令,也是最基本的編程指令,用于將一個(gè)數(shù)據(jù)從源地址傳送到目標(biāo)地址(寄存器間的數(shù)據(jù)傳送本質(zhì)上也是一樣的)。這篇文章給大家介紹匯編語(yǔ)言mov指令及基本用法,感興趣的朋友一起看看吧
    2020-01-01
  • 匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn)

    匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn)

    這篇文章主要介紹了匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 匯編語(yǔ)言MIPS指令分類及尋址模式原理概念

    匯編語(yǔ)言MIPS指令分類及尋址模式原理概念

    這篇文章主要為大家介紹了匯編語(yǔ)言MIPS指令分類及尋址模式的原理及概念,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11

最新評(píng)論