int類型取余導(dǎo)致的core定位過程

1、問題現(xiàn)象

線上服務(wù)每隔一個多月會出現(xiàn)一次core,core在一個多線程庫的queue里面。

queue使用循環(huán)數(shù)組實現(xiàn),里面主要有以下數(shù)據(jù)成員:

{size_t len;/*數(shù)組長度*/ olatile size_t head;/*隊列頭*/ volatile size_t tail;/*隊列尾*/ T* array;/*數(shù)組指針*/}

core的調(diào)用棧位置:array[tail] = std::move(val); core在向隊列尾添加消息的語句。

dmesg信息:segfault at 2872fa0 ip 000000000047e9e3 sp 00007fcc94ffd360 error 4,非法地址是2872fa0,core的位置是47e9e3。

2、使用objdump命令將可執(zhí)行文件反匯編。

array[tail] = std::move(val);語句對應(yīng)的匯編代碼如下:

%rbx存的是queue對象,(%rbx)對應(yīng)qlen,0x8(%rbx)對應(yīng)head,0x10(%rbx)對應(yīng)tail,0x18(%rbx)對應(yīng)array。

%rax中存的是無效地址2872fa0,%rax = array + 8*tail。

3、查看core文件中寄存器的內(nèi)容,使用info registers命令。

4、查看%rbx指向的內(nèi)存的內(nèi)容,從中可以得到queue中成員變量的值,使用x命令。

可以看出:tail = 4712592,array = 4713248,array + 8 * tail = 4713248 +? 8 * 4712592 = 42413984 = 2872fa0,正好是引起core的無效地址。

進一步發(fā)現(xiàn) qlen = 4708768,head = 4708864,發(fā)現(xiàn)可疑的地方,首先qlen沒有這么大,我們設(shè)置的qlen應(yīng)該等于遠小于這個值,另外qlen也不應(yīng)該小于head和tail,這時候考慮可能由兩種情況導(dǎo)致的:(1)queue對象的內(nèi)容被飛踩了(2)queue對象是不是獲取錯了??紤]到queue對象被飛踩定位比較難,所以先檢查queue對象獲取的是否正確。

5、進一步檢查代碼,發(fā)現(xiàn)多線程庫中會有多個Consumer,每個Consumer對應(yīng)一個queue對象,將一個消息發(fā)送給哪個queue是由我們業(yè)務(wù)根據(jù)輪詢選擇的,輪詢的代碼(worker++%worker_num),而worker定義成int型,int型當加到最大值后會出現(xiàn)翻轉(zhuǎn)變成負數(shù),對負數(shù)取余還是負數(shù),將一個負數(shù)付給一個ulong型就會變成一個很大的數(shù),導(dǎo)致獲取的queue對象不正確,最終導(dǎo)致core。

6、進一步驗證,用f命令進入業(yè)務(wù)層代碼的frame,用info locals命令查看worker變量的值。

worker為負數(shù),驗證了問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容