android ndk空指針導致CRASH的問題

1. APP啓動時隔三差五地隨機性地CRASH,捕捉到的日誌:

----------------
2013-06-03 10:26:52
----------------
#00  pc 0002e9b4  /data/data/com.XXXX.map/lib/libmapengine.so
#01  lr 8082dc97  /data/data/com.XXXX.map/lib/libmapengine.so

2. CRASH在彙編碼2e9b4位置,通過objdump工具生成so包對應的彙編文件,查找定位crash位置:

0002e9b4 <_ZN12TextureCache15ensureCacheSizeEi>:
   2e9b4:	6803      	ldr	r3, [r0, #0]
   2e9b6:	428b      	cmp	r3, r1
   2e9b8:	da00      	bge.n	2e9bc <_ZN12TextureCache15ensureCacheSizeEi+0x8>
   2e9ba:	6001      	str	r1, [r0, #0]
   2e9bc:	4770      	bx	lr
第一行 2e9b4位置。

3. 對應ensureCacheSize函數源碼:

void TextureCache::ensureCacheSize(int size){
	if(limit < size){
		limit = size;
	}
}

看到函數源碼以後,一時有點丈二摸不着頭腦了,函數內部就一個if判斷,何來的crash?2e9b4位置而且是一個ldr尋址操作,根據彙編源碼得知是取limit成員變量值。

4. 跟一位經驗豐富地同事討論,他說這是典型地空指針導致的CRASH問題,原因如下:

這個函數如此調用:tileTexCache->ensureCacheSize(blkNum + 1); 當tileTexCache指針爲空時,並不是在函數調用這行CRASH,而是在成員函數內部。

原理《C++對象模型》書中有講解:C++中類的成員函數和成員變量不太一樣,成員變量定義在對象內部,跟對象一個級別,與this指針有關;而成員函數則定義在類內部,跟類一個級別,與this指針無關。換個角度理解這句話,即使對象指針爲空,通過空對象指針訪問成員函數也是可以,只有當成員函數內部需要訪問成員變量時纔會CRASH,因爲成員變量定義在對象內部。這個道理我懂,但怎麼也跟空指針聯繫起來!

5. 測試DEMO

class EmptyPointerApp 
{
public:
	void safeFunc() 
	{
		cout << "World Peace" << endl;
	}

	void badFunc() 
	{
		cout << "Will Crash" << endl;
		mData = 1;
	}

private:
	int mData;
};

int main(int argc, char** argv)
{
	EmptyPointerApp* pSample = NULL;
	pSample->safeFunc();
	pSample->badFunc();
}
vs2008,CRASH在mData=1語句,此時輸出:

World Peace
Will Crash
調試中斷後打開反彙編窗口:


第一個mov將this指針內容放到eax寄存器中,dword ptr指明瞭指令訪問內存的單元是一個dword,即四個字節長度。

第二個mov通過eax訪問mData成員時CRASH!






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章