一、linux:
當程序運行的過程中異常終止或崩潰,操作系統會將程序當時的內存狀態記錄下來,保存在一個文件中,這種行為就叫做Core Dump(“核心轉儲”)。可以認為 core dump 是“內存快照”,但實際上,除了內存信息之外,還有些關鍵的程序運行狀態也會同時dump 下來,例如寄存器信息(包括程序指針、棧指針等)、內存管理信息、其他處理器和操作系統狀態和信息。core dump對於編程人員診斷和調試程序是非常有幫助的,因為對於有些程序錯誤是很難重現的,例如指針異常,而 core dump 文件可以再現程序出錯時的情景。
Core Dump 如何產生
上面說當程序運行過程中異常終止或崩潰時會發生core dump,但沒說什么具體的情景程序會發生異常終止或崩潰,例如我們使用 kill -9
命令殺死一個進程會發生 core dump 嗎?實驗證明是不能的,那么什么情況會產生呢?
Linux 中信號是一種異步事件處理的機制,每種信號對應有其默認的操作,你可以在 這里 查看 Linux 系統提供的信號以及默認處理。默認操作主要包括忽略該信號(Ingore)、暫停進程(Stop)、終止進程(Terminate)、終止並發生core dump(core)等。如果我們信號均是采用默認操作,那么,以下列出幾種信號,它們在發生時會產生 core dump:
Signal |
Action |
Comment |
SIGQUIT |
Core |
Quit from keyboard |
SIGILL |
Core |
Illegal Instruction |
SIGABRT |
Core |
Abort signal from abort |
SIGSEGV |
Core |
Invalid memory reference |
SIGTRAP |
Core |
Trace/breakpoint trap |
當然不僅限於上面的幾種信號。這就是為什么我們使用 Ctrl+z
來掛起一個進程或者 Ctrl+C
結束一個進程均不會產生 core dump,因為前者會向進程發出 SIGTSTP 信號,該信號的默認操作為暫停進程(Stop Process);后者會向進程發出SIGINT 信號,該信號默認操作為終止進程(Terminate Process)。同樣上面提到的 kill -9
命令會發出 SIGKILL 命令,該命令默認為終止進程。而如果我們使用 Ctrl+\
來終止一個進程,會向進程發出 SIGQUIT 信號,默認是會產生 core dump 的。還有其它情景會產生 core dump, 如:程序調用 abort()
函數、訪存錯誤、非法指令等等。
下面舉兩個例子來說明:
- 終端下比較
Ctrl+C
和Ctrl+\
: - 小程序產生 core dump
· guohailin@guohailin:~$ sleep 10 #使用sleep命令休眠 10 s
· ^C #使用 Ctrl+C 終止該程序,不會產生 core dump
· guohailin@guohailin:~$ sleep 10
· ^\Quit (core dumped) #使用 Ctrl+\ 退出程序,會產生 core dump
· guohailin@guohailin:~$ ls #多出下面一個 core 文件
· -rw------- 1 guohailin guohailin 335872 10月 22 11:31 sleep.core.21990
· #include <stdio.h>
·
· int main()
· {
· int *null_ptr = NULL;
· *null_ptr = 10; //對空指針指向的內存區域寫,會發生段錯誤
· return 0;
· }
· #編譯執行
· guohailin@guohailin:~$ ./a.out
· Segmentation fault (core dumped)
· guohailin@guohailin:~$ ls #多出下面一個 core 文件
· -rw------- 1 guohailin guohailin 200704 10月 22 11:35 a.out.core.22070
Linux 下打開 Core Dump
我使用的 Linux 發行版是 Ubuntu 13.04,設置生成 core dump 文件的方法如下:
- 打開 core dump 功能
- 在終端中輸入命令
ulimit -c
,輸出的結果為 0,說明默認是關閉 core dump 的,即當程序異常終止時,也不會生成 core dump 文件。 - 我們可以使用命令
ulimit -c unlimited
來開啟 core dump 功能,並且不限制 core dump 文件的大小; 如果需要限制文件的大小,將 unlimited 改成你想生成 core 文件最大的大小,注意單位為 blocks(KB)。 - 用上面命令只會對當前的終端環境有效,如果想需要永久生效,可以修改文件
/etc/security/limits.conf
文件,關於此文件的設置參看 這里 。增加一行: - 修改 core 文件保存的路徑
- 默認生成的 core 文件保存在可執行文件所在的目錄下,文件名就為
core
。 - 通過修改
/proc/sys/kernel/core_uses_pid
文件可以讓生成 core 文件名是否自動加上 pid 號。
例如echo 1 > /proc/sys/kernel/core_uses_pid
,生成的 core 文件名將會變成core.pid
,其中 pid 表示該進程的 PID。 - 還可以通過修改
/proc/sys/kernel/core_pattern
來控制生成 core 文件保存的位置以及文件名格式。
例如可以用echo "/tmp/corefile-%e-%p-%t" > /proc/sys/kernel/core_pattern
設置生成的 core 文件保存在 “/tmp/corefile” 目錄下,文件名格式為 “core-命令名-pid-時間戳”。這里 有更多詳細的說明!
· # /etc/security/limits.conf
· #
· #Each line describes a limit for a user in the form:
· #
· #<domain> <type> <item> <value>
· * soft core unlimited
使用 gdb 調試 Core 文件
產生了 core 文件,我們該如何使用該 Core 文件進行調試呢?Linux 中可以使用 GDB 來調試 core 文件,步驟如下:
- 首先,使用 gcc 編譯源文件,加上
-g
以增加調試信息; - 按照上面打開 core dump 以使程序異常終止時能生成 core 文件;
- 運行程序,當core dump 之后,使用命令
gdb program core
來查看 core 文件,其中 program 為可執行程序名,core 為生成的 core 文件名。
下面用一個簡單的例子來說明:
#include <stdio.h>
int func(int *p)
{
int y = *p;
return y;
}
int main()
{
int *p = NULL;
return func(p);
}
編譯加上調試信息,運行之后core dump,使用 gdb 查看 core 文件。
guohailin@guohailin:~$ gcc core_demo.c -o core_demo -g
guohailin@guohailin:~$ ./core_demo
Segmentation fault (core dumped)
guohailin@guohailin:~$ gdb core_demo core_demo.core.24816
...
Core was generated by './core_demo'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483cd in func (p=0x0) at core_demo.c:5
5 int y = *p;
(gdb) where
#0 0x080483cd in func (p=0x0) at core_demo.c:5
#1 0x080483ef in main () at core_demo.c:12
(gdb) info frame
Stack level 0, frame at 0xffd590a4:
eip = 0x80483cd in func (core_demo.c:5); saved eip 0x80483ef
called by frame at 0xffd590c0
source language c.
Arglist at 0xffd5909c, args: p=0x0
Locals at 0xffd5909c, Previous frame's sp is 0xffd590a4
Saved registers:
ebp at 0xffd5909c, eip at 0xffd590a0
(gdb)
從上面可以看出,我們可以還原 core_demo 執行時的場景,並使用 where
可以查看當前程序調用函數棧幀,還可以使用 gdb 中的命令查看寄存器,變量等信息。
舉例快速上手:
[root@yunji tmp]# sleep 1000
[root@yunji ~]# ps -ef|grep sleep
在‘sleep 1000’命令下,輸入:control+\,顯示:
^\退出(core)
查看有無core文件生成:
[root@yunji tmp]# gdb program corefile-sleep-31318-1628152235
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... program: 沒有那個文件或目錄. [New LWP 31318] Missing separate debuginfo for the main executable file Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/bb/e03535757d35ca69c622cb8d59501fe8db932f Core was generated by `sleep 1000'. Program terminated with signal 3, Quit. #0 0x00007f56af7908d0 in ?? () (gdb)
問題:顯示了沒有進程。
二、mac:
開啟coredump:
%ulimit -c unlimited
查看進程:
不指定目錄,core文件均存在/cores 目錄中。
cd /cores
ls
運行 lldb -c “core文件的名稱”
lldb -c core.2112
warning: (x86_64) /cores/core.21126 load command 1188 LC_SEGMENT_64 has a fileoff (0x23aee5a5c8) that extends beyond the end of the file (0x95799000), ignoring this section
運行bt就可以看到程序崩潰時的堆棧信息了。
三、windows:
在 Windows 10 上,每次發生崩潰時,系統都會創建一個“轉儲”文件,其中包含錯誤發生時的內存信息,可以幫助確定問題的原因。
“.dmp”文件包括停止錯誤消息、出現問題時加載的驅動程序列表、內核、處理器和進程詳細信息,以及其他取決於您使用的轉儲文件類型的信息。
Windows 10自動創建的轉儲文件可使用Microsoft WinDbg 工具(Windows 調試內核模式和用戶模式代碼、檢查處理器注冊表和分析故障轉儲工具)調試。
1、安裝 WinDbg步驟:
1)打開您喜歡的瀏覽器。
3)單擊獲取(或安裝/打開)按鈕。
4)單擊打開按鈕。
5)單擊安裝按鈕。
完成這些步驟后,將安裝該應用程序,並可通過“開始”菜單使用它。
2、分析轉儲文件
要打開和分析由 Windows 10 崩潰創建的轉儲文件步驟:
1)打開開始。
2)搜索WinDbg,右鍵單擊頂部結果,選擇以管理員身份運行選項。
3)單擊文件菜單。
4)單擊開始調試。
5)選擇打開油槽文件選項。
6)從文件夾位置選擇轉儲文件 - 例如,%SystemRoot%\Minidump
.
7)單擊打開按鈕。
8)檢查進度條,直到它加載轉儲文件(這可能需要一段時間)。
9)在運行命令中鍵入以下命令並按Enter 鍵:
!analyze -v
快速提示:您還可以單擊!analyze -v鏈接(如果在加載轉儲文件后可用)從主區域可用。
10)檢查進度條直到分析完成(這可能需要很長時間,具體取決於數據大小)。
完成這些步驟后,應用程序將返回轉儲文件分析,然后您可以查看這些分析以確定問題的原因以幫助您解決問題。
信息會因問題而異。例如,此測試轉儲文件顯示藍屏死機 (BSoD)(也稱為錯誤檢查)的信息。
結果指出這是一個帶有“e2”錯誤代碼的手動啟動的崩潰,這是正確的,因為出於本指南的目的,我們使用這些指令來強制 BSoD。WinDbg 甚至出色地用任何人都能理解的語言描述了崩潰(用戶手動啟動了此崩潰轉儲)。
當繼續查看轉儲文件時,您還會發現更多信息,例如“FAILURE_BUCKET_ID”和“MODULE_NAME”,它們可以指出導致問題的原因。
參考:
https://www.cnblogs.com/hazir/p/linxu_core_dump.html
https://www.windowscentral.com/how-open-and-analyze-dump-error-files-windows-10