目錄
環(huán)境
問(wèn)題情況
解決思路
原因分析
解決方法
番外知識(shí)
環(huán)境
- VMware? Workstation 16 Pro (版本:16.1.2 build-17966106)
- ubuntu-22.04.2-desktop-amd64
問(wèn)題情況
- 本人在運(yùn)行百萬(wàn)并發(fā)的服務(wù)端程序時(shí),程序運(yùn)行報(bào):段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ)),導(dǎo)致程序異常退出,如下
![]()
解決思路
- 首先要確定核心轉(zhuǎn)儲(chǔ)文件的生成路徑和大小限制。然后使用調(diào)試器(如 GDB)來(lái)分析核心轉(zhuǎn)儲(chǔ)文件和堆棧跟蹤信息后,修復(fù)代碼中導(dǎo)致“段錯(cuò)誤”的原因。
原因分析
1.什么是段錯(cuò)誤?
- 段錯(cuò)誤(Segmentation Fault)是一種常見(jiàn)的程序錯(cuò)誤,通常在訪問(wèn)無(wú)效的內(nèi)存地址時(shí)發(fā)生。當(dāng)程序試圖訪問(wèn)一個(gè)不屬于它的內(nèi)存段時(shí),操作系統(tǒng)會(huì)發(fā)送一個(gè)信號(hào)(SIGSEGV(段錯(cuò)誤信號(hào)))給程序,稱為段錯(cuò)誤。
2.可能產(chǎn)生段錯(cuò)誤的情況
- 內(nèi)存訪問(wèn)錯(cuò)誤:最常見(jiàn)的原因之一是程序試圖訪問(wèn)無(wú)效的內(nèi)存地址或未初始化的指針。這可能是由于代碼錯(cuò)誤、緩沖區(qū)溢出或內(nèi)存越界等造成的。當(dāng)程序嘗試訪問(wèn)系統(tǒng)不允許訪問(wèn)的內(nèi)存區(qū)域時(shí),操作系統(tǒng)會(huì)引發(fā)段錯(cuò)誤。
- 無(wú)效的指令或操作:另一個(gè)常見(jiàn)原因是程序執(zhí)行了無(wú)效的指令或操作。這可能是由于編譯錯(cuò)誤、錯(cuò)誤的代碼邏輯或架構(gòu)不兼容性等引起的。當(dāng)處理器嘗試執(zhí)行無(wú)效的指令或操作時(shí),會(huì)導(dǎo)致段錯(cuò)誤。
- 動(dòng)態(tài)內(nèi)存分配問(wèn)題:使用動(dòng)態(tài)內(nèi)存分配(如?
malloc
?或?new
)時(shí),如果出現(xiàn)內(nèi)存泄漏、重復(fù)釋放已釋放的內(nèi)存或訪問(wèn)已釋放的內(nèi)存等問(wèn)題,可能導(dǎo)致段錯(cuò)誤。這些問(wèn)題可能是由于錯(cuò)誤的內(nèi)存管理導(dǎo)致的。- 棧溢出:如果程序的??臻g超出了其允許的范圍,例如無(wú)限遞歸調(diào)用或大量局部變量使用導(dǎo)致的棧溢出,會(huì)產(chǎn)生段錯(cuò)誤。
- 庫(kù)或依賴項(xiàng)問(wèn)題:有時(shí),段錯(cuò)誤可能是由于使用損壞的庫(kù)、不兼容的版本或缺少的依賴項(xiàng)引起的。庫(kù)的錯(cuò)誤使用或配置問(wèn)題可能導(dǎo)致段錯(cuò)誤。
- 硬件問(wèn)題:雖然比較罕見(jiàn),但硬件故障(如內(nèi)存損壞)也可能導(dǎo)致程序報(bào)告段錯(cuò)誤并生成核心轉(zhuǎn)儲(chǔ)。
3.核心已轉(zhuǎn)儲(chǔ)是轉(zhuǎn)儲(chǔ)到那兒?
- 當(dāng)程序發(fā)生段錯(cuò)誤時(shí),操作系統(tǒng)會(huì)生成一個(gè)名為?
core
?或?core.<進(jìn)程ID>
?的核心轉(zhuǎn)儲(chǔ)文件,其中包含了程序崩潰時(shí)的內(nèi)存映像和其他相關(guān)信息。這個(gè)core文件通常會(huì)被轉(zhuǎn)儲(chǔ)到當(dāng)前工作目錄下。- 但我的 core 文件并沒(méi)有生成到程序的工作目錄下,看下面解決...
解決方法
1.檢查操作系統(tǒng)的核心轉(zhuǎn)儲(chǔ)文件(core dump file)生成設(shè)置
- 使用命令?
ulimit -a
?查看當(dāng)前的核心轉(zhuǎn)儲(chǔ)文件大小限制和其他限制信息![]()
- 查找輸出中的"core file size"(核心轉(zhuǎn)儲(chǔ)文件大?。┳侄?,紅框中的?
0
?表示當(dāng)前禁用了核心轉(zhuǎn)儲(chǔ)文件的生成??梢愿倪@個(gè)限制來(lái)啟用核心轉(zhuǎn)儲(chǔ)文件的生成。
2.更改 "core file size”字段 的限制來(lái)啟用核心轉(zhuǎn)儲(chǔ)文件的生成
使用?ulimit -c unlimited
?命令可以將core文件的大小限制設(shè)置為無(wú)限制,但通過(guò)(不推薦)ulimit
命令設(shè)置的參數(shù)僅在當(dāng)前 shell 進(jìn)程生效,也就是當(dāng)前會(huì)話。一旦關(guān)閉終端窗口,設(shè)置將被重置為默認(rèn)值。因此,這種修改并不是永久性的。- 如果想要在系統(tǒng)級(jí)別永久修改core文件的生成大小限制,需要進(jìn)行操作系統(tǒng)的配置更改??梢酝ㄟ^(guò)修改?
/etc/security/limits.conf
?文件來(lái)設(shè)置core文件大小限制。添加或修改下面兩行:
- *?? ?soft ? ?core?? ?unlimited
- *?? ?hard ? ?core?? ?unlimited
- 重啟虛擬機(jī),重新加載系統(tǒng)的參數(shù)配置,以確保更改生效(重啟命令: sudo reboot)
![]()
3.話不多說(shuō),直接測(cè)試一下
- 不想跑服務(wù)端程序了,太費(fèi)時(shí)了,直接寫一個(gè)測(cè)試?yán)踝?,代碼如下:
![]()
- 運(yùn)行該測(cè)試?yán)踝雍螅](méi)有在工程目錄下生成 core 文件。
![]()
4.確定一下 core 文件的生成路徑
- 查找資料說(shuō)Linux 內(nèi)核有一個(gè)參數(shù)
kernel.core_pattern
,用于指定生成核心轉(zhuǎn)儲(chǔ)文件時(shí)的文件名和路徑模式,相關(guān)的配置文件為/proc/sys/kernel/core_pattern
。而在 Linux 中,可以使用?sysctl
?命令來(lái)檢查和更改核心轉(zhuǎn)儲(chǔ)文件的生成路徑限制。- 然后使用?
sysctl kernel.core_pattern
?命令來(lái)查看當(dāng)前的核心轉(zhuǎn)儲(chǔ)文件生成路徑。它輸出了下面一行內(nèi)容:
- kernel.core_pattern = |/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
- 上面這一行是啥意思呢,解釋如下:
|/usr/share/apport/apport
: 它是一個(gè)特殊的核心轉(zhuǎn)儲(chǔ)處理程序(core dump handler),它是一個(gè)用于收集和報(bào)告故障的工具。當(dāng)進(jìn)程收到?SIGSEGV
?或類似的信號(hào)時(shí),內(nèi)核將使用?kernel.core_pattern
?中指定的處理程序來(lái)處理和處理核心轉(zhuǎn)儲(chǔ)文件。%p
: 進(jìn)程 ID。%s
: 目前正在運(yùn)行的線程 ID。%c
: 產(chǎn)生核心轉(zhuǎn)儲(chǔ)文件的信號(hào)代碼。%d
: 序列號(hào),用于確保在同一目錄中生成的核心轉(zhuǎn)儲(chǔ)文件具有唯一的名稱。%P
: 父進(jìn)程 ID。%u
: 用戶名。%g
: 組名。%E
: 產(chǎn)生核心轉(zhuǎn)儲(chǔ)文件的可執(zhí)行文件全路徑。- 具體而言,
/usr/share/apport/apport
?是一個(gè)用于 Ubuntu 系統(tǒng)的工具,它可以收集有關(guān)崩潰和故障的信息,并生成相應(yīng)的錯(cuò)誤報(bào)告。
5.修改?core 文件的生成路徑
- 可以使用?
sudo sysctl -w kernel.core_pattern=<path_to_directory>/core
?命令將其恢復(fù)為期望的路徑。確保?<path_to_directory>
?是一個(gè)有效的目錄路徑。比如
- sudo sysctl -w kernel.core_pattern=core
- 重新編譯一下,在當(dāng)前目錄下生成了?
core.<進(jìn)程ID>
?的核心轉(zhuǎn)儲(chǔ)文件,如下![]()
- 注意:以上方式修改?
kernel.core_pattern
?的值只在運(yùn)行時(shí)生效,并不是永久的,在系統(tǒng)重啟后,該更改將被重置為默認(rèn)值。- 可以了解最后一節(jié)“番外知識(shí)”
6.使用調(diào)試工具 gdb 來(lái)加載和分析 core 文件
- 生成核心文件:使用 gcc 編譯記得加 -g 命令。
![]()
- 加載核心文件:使用gdb命令行加載核心文件,將核心文件加載到調(diào)試環(huán)境中。
- gdb <可執(zhí)行文件路徑> <核心文件路徑>
- 查看堆棧回溯:運(yùn)行g(shù)db后,使用
bt
命令(或backtrace
)來(lái)查看堆棧回溯,它將顯示程序在崩潰時(shí)的函數(shù)調(diào)用鏈。
- (gdb) bt
- 檢查變量值:你可以使用
- (gdb) print variable_name
- 跳轉(zhuǎn)到特定幀:使用
frame
命令可以在堆棧幀之間進(jìn)行導(dǎo)航,并查看在特定幀上的堆棧信息。幀編號(hào)通常是從0開(kāi)始按逆序分配的,也就是最底部幀的編號(hào)是0。
- (gdb) frame frame_number
- 分析原因:分析堆?;厮莺妥兞恐?,可以幫助你定位程序崩潰的原因。一般情況下,最底部的堆棧幀提供了最初崩潰的位置。
- 操作如下:說(shuō)明 *P 未初始化
![]()
番外知識(shí)
1.對(duì) /proc/sys/kernel/core_pattern 可以添加可寫權(quán)限嗎?
- 答案是不可以。默認(rèn)權(quán)限如下(所有者具有讀寫權(quán)限,組用戶和其他用戶只有讀取權(quán)限)。
![]()
- 對(duì)于
/proc/sys/kernel/core_pattern
文件,不能直接添加可讀權(quán)限。這是因?yàn)?code>/proc目錄和其下的文件是虛擬文件系統(tǒng)(procfs
)的一部分,用于提供對(duì)內(nèi)核和進(jìn)程信息的訪問(wèn),它們的權(quán)限和所有權(quán)是由內(nèi)核控制的,而不受Linux文件系統(tǒng)權(quán)限模型的限制。- 在
/proc
目錄中,每個(gè)文件和目錄的權(quán)限通常被設(shè)置為只讀,不允許用戶直接修改它們的權(quán)限。這是為了確保提供的信息的完整性和一致性,并防止對(duì)內(nèi)核和進(jìn)程狀態(tài)的非授權(quán)更改。- 因此,無(wú)法通過(guò)常規(guī)的?
chmod
?命令或其他方式直接向?/proc/sys/kernel/core_pattern
添加可讀權(quán)限或更改其權(quán)限。嘗試執(zhí)行類似以下命令時(shí)會(huì)出現(xiàn)錯(cuò)誤:
- sudo chmod +w /proc/sys/kernel/core_pattern
- 你會(huì)收到“Operation not permitted”或“不允許的操作”類似的錯(cuò)誤消息。
![]()
2.在系統(tǒng)重啟后,對(duì)?
/proc/sys/kernel/core_pattern
?文件的更改為什么被重置為默認(rèn)值?
- 這是因?yàn)?code>/proc/sys/目錄中的文件是在內(nèi)核啟動(dòng)期間動(dòng)態(tài)生成的,其值來(lái)自于內(nèi)核參數(shù)或其他系統(tǒng)設(shè)置。在系統(tǒng)重啟時(shí),這些文件會(huì)重新加載為其默認(rèn)值或由某些配置文件指定的值。
3.怎么實(shí)現(xiàn)永久性修改
/proc/sys/kernel/core_pattern
?文件呢?(這條有問(wèn)題)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-736955.html
- 編輯
/etc/sysctl.conf
文件:(這種方式不太好,每次系統(tǒng)重啟后要執(zhí)行一下 sudo sysctl -p 命令才會(huì)修改/proc/sys/kernel/core_pattern的值)
- 可以編輯?
/etc/sysctl.conf
?文件,將核心轉(zhuǎn)儲(chǔ)文件模式的修改添加到該文件中,添加內(nèi)容如下:
- kernel.core_pattern = core
- 在保存并退出文件后,使用以下命令重新加載配置,使新的核心轉(zhuǎn)儲(chǔ)文件模式生效:
- sudo sysctl -p
- 創(chuàng)建并編輯系統(tǒng)啟動(dòng)腳本:可以編寫一個(gè)腳本,以在系統(tǒng)啟動(dòng)時(shí)將核心轉(zhuǎn)儲(chǔ)文件模式設(shè)置為所需的值。將腳本放置在適當(dāng)?shù)奈恢?,例?code>/etc/init.d/目錄,并設(shè)置為在系統(tǒng)啟動(dòng)時(shí)執(zhí)行。(測(cè)試了沒(méi)有用)
- 創(chuàng)建啟動(dòng)腳本文件:在所選擇的目錄中創(chuàng)建一個(gè)新文件
- sudo vim /etc/init.d/my_startup_script.sh
- 編寫啟動(dòng)腳本:在腳本中添加如下內(nèi)容,保存成功并退出。
- #!/bin/bash
- echo "core" >> /proc/sys/kernel/core_pattern
- exit 0
- 賦予腳本執(zhí)行權(quán)限:使用以下命令為啟動(dòng)腳本文件賦予執(zhí)行權(quán)限
- sudo chmod +x /etc/init.d/my_startup_script.sh
- 配置啟動(dòng)腳本的執(zhí)行:將啟動(dòng)腳本添加到系統(tǒng)的啟動(dòng)過(guò)程中,以確保在系統(tǒng)啟動(dòng)時(shí)執(zhí)行
- sudo update-rc.d my_startup_script.sh defaults
- 若要禁用腳本的啟動(dòng),可以使用以下命令(了解)
- sudo update-rc.d -f my_startup_script.sh remove
注意文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-736955.html
- 需要注意的是,更改?
/proc/sys/kernel/core_pattern
?文件的權(quán)限和內(nèi)容是敏感操作,可能會(huì)影響系統(tǒng)的穩(wěn)定性和安全性。務(wù)必小心謹(jǐn)慎,并確保了解所做更改的影響。
到了這里,關(guān)于【問(wèn)題記錄】Ubuntu 22.04 環(huán)境下,程序報(bào):段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))怎么使用 core 文件和GDB調(diào)試器 解決?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!