空指標訪問的陷阱

2021-09-19 18:24:00 字數 3600 閱讀 7710

asan工具報錯發生在如下行,此處maudiorenderserviceptr為null。

this->onstop(false, maudiorenderserviceptr->getaddr());
下面對正常執行和工具除錯出現的結果一致進行分析,以及延伸的討論一下關於空指標訪問的一些陷阱。

空指標即未指向任何物件,於是從語言層面來講在訪問空指標時應該一定發生崩潰,但在多函式呼叫及引數傳遞過程中,以及c++語言的封裝特性、編譯器是否優化的情況下,則不一定發生崩潰或者崩潰延遲。

先看看getaddr這個成員函式的宣告:

const mdfaddr& getaddr()

這裡發現返回值為成員變數maddr的常量引用,如下是反彙編對應的指令

0xad0b9880 <+512>: ldr.w  r0, [r5, #0x124]

0xad0b9884 <+516>: movs r1, #0x0

0xad0b9886 <+518>: add.w r2, r0, #0x3c

從彙編指令看到,最後一行直接將this指標加上成員變數的偏移值0x3c並返回,也即返回的是maddr的位址0x3c。

以及成員函式onstop的函式宣告

void onstop(bool isasync, const mdfaddr &srcaddr);

第二個引數實際使用的是mdfaddr的常量引用,因此引數會直接傳遞其物件位址0x3c,而不會訪問0x3c指向的記憶體值,後面函式執行過程中也並未訪問maddr的成員變數,所以無工具執行時不會發生崩潰。

至於有工具時會發生崩潰,是因為asan會對所有位址訪問進行監控,當出現異常時就會中斷崩潰。

void onstop(bool isasync, mdfaddr srcaddr);

第二個引數會直接傳遞mdfaddr的值,因此會訪問0x3c指向的實際記憶體,從而會立即導致崩潰,輸出類似如下的資訊

build fingerprint: 'xiaomi/cancro_wc_lte/cancro:6.0.1/mmb29m/8.9.13:user/release-keys'

02-21 16:43:27.589 290-290/? a/debug: revision: '0'

02-21 16:43:27.589 290-290/? a/debug: abi: 'arm'

02-21 16:43:27.589 290-290/? a/debug: pid: 19854, tid: 19933, name: thread-3246 >>> com.aliyun.aliyunvideosdkpro <<<

02-21 16:43:27.589 290-290/? a/debug: signal 6 (sigabrt), code -6 (si_tkill), fault addr --------

02-21 16:43:27.610 290-290/? a/debug: r0 00000000 r1 00004ddd r2 00000006 r3 99c11978

02-21 16:43:27.610 290-290/? a/debug: r4 99c11980 r5 99c11930 r6 00000019 r7 0000010c

02-21 16:43:27.610 290-290/? a/debug: r8 0000000b r9 b3472bd0 sl 00000000 fp 133822cc

02-21 16:43:27.610 290-290/? a/debug: ip 00000006 sp a8260188 lr b6816c69 pc b6819058 cpsr 400d0010

02-21 16:43:27.646 290-290/? a/debug: backtrace:

02-21 16:43:27.646 290-290/? a/debug: #00 pc 00042058 /system/lib/libc.so (tgkill+12)

02-21 16:43:27.646 290-290/? a/debug: #01 pc 0003fc65 /system/lib/libc.so (pthread_kill+32)

02-21 16:43:27.646 290-290/? a/debug: #02 pc 0001c403 /system/lib/libc.so (raise+10)

02-21 16:43:27.646 290-290/? a/debug: #03 pc 000195b5 /system/lib/libc.so (__libc_android_abort+34)

02-21 16:43:27.646 290-290/? a/debug: #04 pc 00017508 /system/lib/libc.so (abort+4)

02-21 16:43:27.647 290-290/? a/debug: #05 pc 000a18b3 /system/lib/libclang_rt.asan-arm-android.so (_zn11__sanitizer5abortev+40)

02-21 16:43:27.647 290-290/? a/debug: #06 pc 000a6449 /system/lib/libclang_rt.asan-arm-android.so (_zn11__sanitizer3dieev+60)

02-21 16:43:27.647 290-290/? a/debug: #07 pc 0008ffc0 /system/lib/libclang_rt.asan-arm-android.so (_zn6__asan19scopedinerrorreportd2ev+352)

02-21 16:43:27.647 290-290/? a/debug: #08 pc 000900b8 /system/lib/libclang_rt.asan-arm-android.so (_zn6__asan18reportdeadlysignaleirkn11__sanitizer13signalcontexte+160)

02-21 16:43:27.647 290-290/? a/debug: #09 pc 0008f0fc /system/lib/libclang_rt.asan-arm-android.so (_zn6__asan18asanondeadlysignaleipvs0_+188)

02-21 16:43:27.647 290-290/? a/debug: #10 pc 0036d2e1 /system/lib/libart.so (_zn3art12faultmanager11handlefaulteip7siginfopv+208)

02-21 16:43:27.647 290-290/? a/debug: #11 pc 0001756c /system/lib/libc.so

class myclass

};

如果我們將一些實際未使用類成員變數的全域性函式作為類的成員函式,那麼在物件指標為null時訪問這一類函式,則不會發生崩潰,因為在執行calcvalue時this指標並不會用到。

非法訪問空指標問題

includeusing namespace std struct listnode int main p1變了,但是指向p1的p2沒有變,結果是非法的 p2是空指標,非法訪問空指標 includeusing namespace std struct listnode int main 這裡也是非法...

C 空指標訪問成員函式

空指標訪問成員函式 class person void showage int m age void test01 可以呼叫show,不能呼叫showage。呼叫show時,編譯器隱式加上了void show person this 雖然此時this p 為空,但是下面的函式裡沒有用到this,所以...

空指標訪問成員函式(3)

c 空指標是可以呼叫成員函式的,但是也要注意有沒有用到this指標。如果用到this指標,需要加以判斷來保證 的健壯性。1 include 2 using namespace std 34 class person512 13void showpersonage int age 1420 21thi...