段錯(cuò)誤(segfault) "段錯(cuò)誤"是程序試圖操作不允許訪問(wèn)或試圖訪問(wèn)的不允許內(nèi)存的情況??赡軐?dǎo)致段錯(cuò)誤的原因主要有: 1、試圖解引用空指針(你不允許訪問(wèn)內(nèi)存地址0) 2、試圖解引用不在你內(nèi)存中的其他指針 3、一個(gè)C vtable虛表指針被破壞并指向錯(cuò)誤的地方,這導(dǎo)致程序試圖去執(zhí)行一些不可執(zhí)行的內(nèi)存。 4、其他情況,比如未對(duì)齊的內(nèi)存訪問(wèn)也可能會(huì)出現(xiàn)段錯(cuò)誤。 core dump 文件 在linux下當(dāng)應(yīng)用程序發(fā)生異常中止退出或者發(fā)生崩潰的時(shí)候,linux內(nèi)核會(huì)將應(yīng)用程序在這段運(yùn)行期間的內(nèi)存狀態(tài)等相關(guān)信息轉(zhuǎn)存到磁盤,以供系統(tǒng)故障排查或者調(diào)試。這個(gè)轉(zhuǎn)存的文件叫core dump文件。core dump文件中會(huì)記錄程序當(dāng)時(shí)的內(nèi)存調(diào)用、堆棧引用、進(jìn)程和線程調(diào)用等信息,可以幫助開(kāi)發(fā)人員和維護(hù)人員了解異常發(fā)生當(dāng)時(shí)的環(huán)境參數(shù)和信息,所以core dump對(duì)故障排查和bug調(diào)試具有重大的意義。 要深入探究還得利用得core dump文件,下面我們就對(duì)其進(jìn)一步探究: 如何獲得core dump 我們前面說(shuō)了core dump是程序發(fā)生異常時(shí)候,其內(nèi)存使用副本的轉(zhuǎn)存文件,當(dāng)你需要調(diào)試程具體序出錯(cuò)時(shí)的信息時(shí)候,它非常有用。 當(dāng)程序發(fā)生段錯(cuò)誤時(shí),Linux內(nèi)核有時(shí)會(huì)向磁盤寫(xiě)入一個(gè)core dump文件。很多人可能疑惑按照教程一步一步來(lái)做了,但是最后沒(méi)有獲得所需的core dump。一般情況下系統(tǒng)設(shè)置不輸出core dump,所以沒(méi)有生成core dump文件。 如果沒(méi)有生成core dump文件,請(qǐng)按照以下步驟做設(shè)置: 1.在linux終端執(zhí)行以下命令 ulimit -c unlimited 2.運(yùn)行sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t ulimit: 在linux下 通過(guò)ulimit -c設(shè)置core dump的最大值。它默認(rèn)設(shè)置為0,這時(shí)候內(nèi)核就不會(huì)生成core dump。它以KB為單位。 ulimit是按進(jìn)程為單位進(jìn)行設(shè)置的。我們可以通過(guò)運(yùn)行cat /proc/PID/limit來(lái)查看具體某個(gè)進(jìn)程的大小限制。 例如,這些是我的系統(tǒng)隨便一個(gè)nginx進(jìn)程的大小限制: cat /proc/8854/limits (PID換成你系統(tǒng)中具體的進(jìn)程號(hào),此處我的系統(tǒng)中進(jìn)程號(hào)位8854) 內(nèi)核通過(guò)soft limit值決定寫(xiě)入core文件的大小 (例如上圖中我們的nginx"max core file size = 0")。我們使用使用ulimit -c unlimited將軟限制無(wú)限制,core dump文件就可以無(wú)限增大。我們也可以用具體文件大小來(lái)替代umlimited的值。 kernel.core_pattern kernel.core_pattern是內(nèi)核參數(shù),通過(guò) sysctl命令來(lái)配置,用于控制Linux內(nèi)核將core dump寫(xiě)入磁盤的位置和文件名格式。 我們可以通過(guò)運(yùn)行sysctl -a來(lái)獲取當(dāng)前系統(tǒng)的所有內(nèi)核參數(shù)和設(shè)置值得列表?;蛘呤褂胹ysctl kernel.core_pattern僅查看kernel.core_pattern的設(shè)置值。 sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t設(shè)置下core dump文件將被寫(xiě)入/tmp/core-(標(biāo)識(shí)進(jìn)程的參數(shù)值)。具體關(guān)于%e.%p.%h參數(shù)的表示內(nèi)容,請(qǐng)參閱man core。 Ubuntu下kernel.core_pattern設(shè)置 默認(rèn)情況下,Ubuntu上, kernel.core_pattern設(shè)置的內(nèi)容為: sysctl kernel.core_pattern kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P 這曾讓我很困惑,這是什么東西,它是怎么處理我的core dump的。所以我搜索相關(guān)資料了解到: Ubuntu使用稱為"apport"的系統(tǒng)來(lái)記錄apt包管理器中的崩潰 設(shè)置kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P 表示core dump內(nèi)容被重定向到apport,其日志為/var/log/apport.log 默認(rèn)情況下,apport將忽略來(lái)非Ubuntu軟件包的二進(jìn)制文件的那部分的崩潰日志。所以默認(rèn)apport.log中默認(rèn)也是不會(huì)記錄core dump信息的。為了得到core dump具體做法就是重新設(shè)置kernel.core_pattern的值,將其設(shè)為sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t。 用gdb進(jìn)行追蹤 core dump中信息是支持用gdb做調(diào)試的,關(guān)于gdb是linux下一個(gè)強(qiáng)大的debug調(diào)試程序,不熟悉的同學(xué),先搜索一下。 用下面的gdb命令打開(kāi)一個(gè)core dump文件: gdb -c my_core_file 接下來(lái),我們想知道程序崩潰時(shí)的堆棧是什么。在gdb提示符下運(yùn)行bt會(huì)給你一個(gè)堆棧追蹤。默認(rèn)情況下,編譯時(shí)候沒(méi)有做符號(hào)調(diào)試,gdb無(wú)法加載二進(jìn)制符號(hào),所以追蹤結(jié)果中會(huì)都是??。如下圖所示: 這種情況下,我們需要加載符號(hào)符號(hào)表,使得顯示正常??赏ㄟ^(guò)在gdb命令下執(zhí)行: symbol-file 應(yīng)用的執(zhí)行程序(絕對(duì)路徑) sharedlibrary 這會(huì)從二進(jìn)制程序文件及其引入的共享庫(kù)中加載符號(hào)。執(zhí)行后,再次輸入bt,gdb就會(huì)返回帶有行號(hào)堆棧跟蹤信息。 如果你想讓其工作正常,在做程序做調(diào)試時(shí)候應(yīng)該啟用哦調(diào)試符號(hào)編譯(gcc -g)。在試圖找出程序崩潰的原因時(shí),在堆棧跟蹤中有行號(hào)非常有用。 在gdb也可以查看每個(gè)線程的堆棧,具體方法如下: thread apply all bt full 來(lái)源:http://www./content-3-154201.html |
|
來(lái)自: 印度阿三17 > 《開(kāi)發(fā)》