一次Linux中定位c++程序運行異常的經(jīng)歷
今天下午我遇到了一些棘手的問題,因為在mips64上編譯程序,經(jīng)常出現(xiàn)程序編譯不出來,或者運行不正常,花了很長的時間定位,最后和同事一些解決了,下面分享出來我提煉出來的一些核心定位問題的步驟。
子線程創(chuàng)建不出來
猜測:go的程序都能創(chuàng)建出子線程,但是c++的創(chuàng)建不出來,但是在 x86 可以,是不是什么 linux 系統(tǒng)限制?
正常表現(xiàn)
異常表現(xiàn)
解決方法:加錯誤日志進行調(diào)試(最 lower 辦法)
找到報錯點:
錯誤日志內(nèi)容
查詢 man 手冊,看看是不是能找到有幫助的東西:
- man pthread_attr_setstacksize
 
打印出解釋:
- ERRORS
 - pthread_attr_setstacksize() can fail with the following error:
 - EINVAL The stack size is less than PTHREAD_STACK_MIN (16384) bytes.
 - On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stacksize is not a multiple of the system page size.
 
翻譯上面的話,可能會產(chǎn)生這個錯誤:
- EINVAL 堆棧大小小于 PTHREAD_STACK_MIN(16384) 字節(jié)。
 - 在某些系統(tǒng)上,如果 stacksize 不是系統(tǒng)頁面大小的倍數(shù), pthread_attr_setstacksize() 可能會失敗,并顯示錯誤 EINVAL
 
查詢 linux 報錯碼含義, 得知錯誤碼 22 果然和 man 手冊中說的一致,是參數(shù)有問題。
錯誤碼對照
第一次嘗試:擴大線程棧到上面說的 16384 ,但還是報錯
錯誤日志內(nèi)容
根據(jù)經(jīng)驗,查看最小頁大小,發(fā)現(xiàn)是 16k , 而 x86 架構(gòu)是 4K ,原來用的 20K 是不對齊的,怪不得創(chuàng)建不出來線程。
查看系統(tǒng)頁大小
依次嘗試, 最終發(fā)現(xiàn) 10*16K 子線程成功創(chuàng)建。
但是不準確,按其說法,應(yīng)該是設(shè)置 PAGESIZE 的整數(shù)倍都行,懷疑其對最小值有要求。c++ 的頭文件在 /usr/include 目錄下面, PTHREAD_STACK_MIN 是一個常量,估計里面會有定義,嘗試查找
- $ grep -rl PTHREAD_STACK_MIN *
 - bits/local_lim.h
 - pthread.h
 
還真讓我找到了, 根據(jù)英文注釋,至少要兩個 64K 作為線程棧,才能跑起一個線程。
系統(tǒng)c++頭文件中的提示信息
至此問題解決。
部分線程卡住
我發(fā)現(xiàn)程序雖然正常運行,但是部分功能不正常,經(jīng)過查看日志發(fā)現(xiàn),有一個線程只執(zhí)行了一半就卡住了。
經(jīng)過查看日志可以定位出是哪個線程卡住,如果從日志看不出來也沒關(guān)系??梢允褂?pstack 進程號 看一些進程堆棧。
查看進程 pid:
- ps -ef |grep 進程名
 
使用 gdb 查看是否出現(xiàn)問題,兩個重要命令:
- gdb attach {pid} #查看正在運行程序的棧
 - info thread #進入以后使用,查看線程信息
 
找到錯誤位置,出現(xiàn)了 fgets() 和 read() 函數(shù),懷疑是此處出現(xiàn)問題。
gdb attach命令結(jié)果
錯誤代碼位置
懷疑 1:_LINE_LENGTH 1024 長度太短,接受命令返回值后超過了數(shù)組本身的長度,覆蓋了未知的內(nèi)存。
這種情況我以前遇到過,表現(xiàn)應(yīng)該是程序直接就崩潰了。
懷疑 2:執(zhí)行命令的時候卡了,導(dǎo)致后面的程序沒有執(zhí)行。
根據(jù) gdb 打印出來的參數(shù),執(zhí)行 linux 命令進行測試,果然是卡在這了!
再次使用 pstree -p {pid} 查看,確實主線程,調(diào)用了 linux 命令卡住。
查看此進程的線程樹
接下來解決卡命令的問題。
解決 1:加 timeout 處理空返回。下面是示例命令,并不是我使用的命令。
- timeout 5 ls -al
 
代表超過 5 秒返回。
解決 2:定位為什么這個 linux 命令會卡住。
- strace ls -al
 
直到解決為止。這就是今晚我加班到 10 點 30 解決的問題,我又用了一個小時總結(jié)下整個過程備忘,希望對你也有幫助。

























 
 
 





 
 
 
 