【Core Dump】核心轉存 故障分析
瀏覽關於coredump的文章時,下面兩篇文章說的清晰易懂,轉發下:
https://blog.csdn.net/asdfghjkl0606/article/details/52841678
https://blog.csdn.net/stpeace/article/details/119699330
http://wjhsh.net/zhchoutai-p-6717780.html
第一篇:簡單介紹coredump基本概念和操作
引言:程式在Linux系統中執行時出錯的時間並不能預測,也許在三分鐘之內程式就崩潰了,也許執行一個月之後才發生錯誤。
如果前一節課學到的GDB除錯,顯然除錯上十天半個月是不可能的。這裡我們用core
dump來解決。
一、Core Dump:資訊轉存、核心轉存。
core dump是一個過程,即Linux會把程式執行過程中發生異常的記憶體內容轉存到core檔案。
core dump主要解決段錯誤(Segment fault)。
二、發生段錯誤的基本原因有:
1、陣列訪問越界;
2、對空指標操作;
3、棧溢位;
4、修改只讀記憶體的內容。
三、啟用/關閉 Core Dump:
開啟:ulimit -c unlimited
關閉:ulimit -c 0
(在Linux系統中預設關閉該功能)
四、Core檔案分析:
在發生core dump之後會在該程式所在路徑下生成一個core檔案。
注意:在編譯程式時需要用-g來加入除錯資訊,否則將讓錯誤逃之夭夭。
> gdb ./test core.13140
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *ptr = NULL;
*ptr = 3;
}
第二篇:告訴你一般定位這類問題的思路
core的最原始含義是磁芯,是一種儲存裝置,dump的意思是倒出,那麼core dump的含義就是:當程序發生異常時,會把當時的記憶體資訊傾倒出來,形成core檔案。
每個做linux C++開發的人,必然會遇到過core dump問題。在C++相關的面試中,core dump的除錯,幾乎是一個必考的考點,旨在檢驗應聘者的實戰除錯經驗。
我知道的一個真實案例是:面試官讓應聘者現場寫出一個core dump程式,結果應聘者很懵圈,不知道怎麼寫。這說明,應聘者沒有相關的除錯經歷,何談通過面試?
接下來,我們以一個簡單的core dump程式為例,來說說除錯core dump的六種經驗和方法,希望能對大家的開發實戰有所幫助,順便地,橫掃那些簡單的面試題。
方法一: 程式碼review
程式碼review,是一種比較原始的笨方法。對於簡單的程式碼而言,還可以進行review, 但是,一旦程式碼達到數萬行,出現core dump後,便無從看起。所以,這種方法很雞肋,幾乎沒什麼用。
方法二: 列印log夾逼
列印log來夾逼,也是一種很簡單的方法,在很多場景下,非常奏效。許多大學生和職場新手,容易出現core dump問題,那麼, 我建議直接用log夾逼。有點類似二分查詢,且看具體的姿勢:其實很多老鳥也是這麼做的。
方法三: dmesg + addr2line
有時候,如果core dump的開關沒有開啟,無法生成core檔案,那怎麼辦呢?也是有辦法的!用dmesg和addr2line吧。關於這兩個命令的介紹,直接man一下即可。且看具體除錯:
以前確實沒用過dmesg。按照上面的操作沒出現相關的段錯誤。
方法四: strace + addr2line
接下來,我們介紹一個重要的linux命令,即strace, 直接man一下就知道,它是用檢視系統呼叫的,我們不過多贅述。來看具體的除錯過程:
後面跟的那串數字是什麼含義?地址? 實際操作的時候可以看到段錯誤。但是addr2line 後面那個a.out沒有對應的。
方法五: valgrind
之前,在除錯記憶體洩漏時,介紹過valgrind,其實valgrind能查其他更多記憶體問題,非常強大。下面,我們來看看valgrind查core dump問題,如下:
valgrind 是 Linux 業內流行且十分強勁的記憶體洩漏查驗專用工具。在其官方網站詳細介紹中,執行記憶體查驗(memcheck)僅僅其在其中一個作用。因為僅用過其記憶體洩漏的查驗,也不擴充套件共享 valgrind 別的作用了。
沒有使用過。暫不描述。
方法六: gdb
gdb除錯,是本文的重頭戲,也幾乎是筆試面試的必考內容。話不多說,直接來看姿勢。使用gdb a.out core(不會重新拉取a.out程序)或者gdb a.out(會重新拉起a.out程序)都可以,如下:
第三篇:linux程式除錯命令addr2line之入門簡單介紹
addr2line有什麼作用呢? 可別小瞧它, 它能夠定位到程式碼出錯的位置。
以下, 我們來看看這個簡單的程式碼:
#include <stdio.h>
int main() { int *p = NULL; *p = 0; printf("bad"); return 0; }
這個程式非常小, 我們能夠一眼就看出程式在執行期出錯。 可是, 假設是大程式, 在執行期出錯。 我們該怎樣定位呢? 那就必須依賴於工具。 而不是你我的肉眼。
我們以上述小程式為例, 進行例如以下操作:
[taoge@localhost learn_c]$ gcc -o taogeSeg -g taogeSeg.c [taoge@localhost learn_c]$ ./taogeSeg Segmentation fault (core dumped) [taoge@localhost learn_c]$ dmesg | grep taogeSeg taogeSeg[4941]: segfault at 0 ip 080483c9 sp bfb92410 error 6 in taogeSeg[8048000+1000] [taoge@localhost learn_c]$ addr2line -e taogeSeg 080483c9 /home/taoge/Desktop/learn_c/taogeSeg.c:6 [taoge@localhost learn_c]$ cat -n taogeSeg.c 1 #include <stdio.h> 2 3 int main() 4 { 5 int *p = NULL; 6 *p = 0; 7 8 printf("bad "); 9 return 0; 10 } [taoge@localhost learn_c]$1. gcc -o taogeSeg -g taogeSeg.c :生成帶有除錯資訊的可執行檔案taogeSeg 2. dmesg | grep taogeSeg :獲得執行taogeSeg後的出錯資訊, 你能夠將結果理解為日誌, 當中的080483c9是一個地址, 正是這個地址出錯了 3. addr2line -e taogeSeg 080483c9 :將出錯地址轉換成原始碼相應的行, 結果為6, 也就是說原始碼第6行有問題。 一看, 果然是,萬惡的*p=0;被揪出來了。
但是我在實際操作過程中,發現dmesg沒有任何相關的linux core資訊出來。不清楚是不是linux版本問題。
我來解釋一下:
當然。 針對這個樣例, 會gdb除錯的朋友肯定也能調試出來,並且也確實能找到程式碼出錯的地址和原始碼行, 從這個意義上來講。 gdb內部也攜帶了類addr2line的功能。這是不是說gdb就能夠替代addr2line呢? 不是的。
假設某bug低概率發生。 如今僅僅有一份crash log, 那就要用addr2line了, 由於你用gdb時。 該bug不一定發生啊。
實際上, 在非常多linux大型軟體開發中, 常常出現段錯誤, 造成程序掛掉, 系統崩潰等問題, 此時, 用addr2line是比較好的方法。
在後面的博文中, 我們會繼續瞭解與addr2line有關的除錯方法, 畢竟, 程式碼除錯太重要了。事實上呢, 假設不熟悉addr2line的使用, 或者乾脆沒有聽說過這個命令, 那最好不要說自己搞linux開發。 免得被人歧視啊。
OK, 本文僅僅是一個引子, 能在實戰中熟練使用addr2line才見真功夫。
如能熟練掌握addr2line的使用。 以後聽到什麼段錯誤, 系統崩潰。 就沒那麼毛骨悚然了。