溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Linux上創建并調試轉儲文件

發布時間:2021-07-30 15:23:28 來源:億速云 閱讀:353 作者:chen 欄目:系統運維

這篇文章主要介紹“怎么在Linux上創建并調試轉儲文件”,在日常操作中,相信很多人在怎么在Linux上創建并調試轉儲文件問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么在Linux上創建并調試轉儲文件”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

崩潰轉儲、內存轉儲、核心轉儲、系統轉儲……這些全都會產生同樣的產物:一個包含了當應用崩潰時,在那個特定時刻應用的內存狀態的文件。

這是一篇指導文章,你可以通過克隆示例的應用倉庫來跟隨學習:

git clone https://github.com/hANSIc99/core_dump_example.git

信號如何關聯到轉儲

信號是操作系統和用戶應用之間的進程間通訊。Linux 使用 POSIX 標準中定義的信號。在你的系統上,你可以在 /usr/include/bits/signum-generic.h 找到標準信號的定義。如果你想知道更多關于在你的應用程序中使用信號的信息,這有一個信息豐富的 signal 手冊頁。簡單地說,Linux 基于預期的或意外的信號來觸發進一步的活動。

當你退出一個正在運行的應用程序時,應用程序通常會收到 SIGTERM 信號。因為這種類型的退出信號是預期的,所以這個操作不會創建一個內存轉儲。

以下信號將導致創建一個轉儲文件(來源:GNU C庫):

  • SIGFPE:錯誤的算術操作

  • SIGILL:非法指令

  • SIGSEGV:對存儲的無效訪問

  • SIGBUS:總線錯誤

  • SIGABRT:程序檢測到的錯誤,并通過調用 abort() 來報告

  • SIGIOT:這個信號在 Fedora 上已經過時,過去在 PDP-11 上用 abort() 時觸發,現在映射到 SIGABRT

創建轉儲文件

導航到 core_dump_example 目錄,運行 make,并使用 -c1 開關執行該示例二進制:

./coredump -c1

該應用將以狀態 4 退出,帶有如下錯誤:

怎么在Linux上創建并調試轉儲文件

Dump written“Abgebrochen (Speicherabzug geschrieben) ”(LCTT 譯注:這是德語,應該是因為本文作者系統是德語環境)大致翻譯為“分段故障(核心轉儲)”。

是否創建核心轉儲是由運行該進程的用戶的資源限制決定的。你可以用 ulimit 命令修改資源限制。

檢查當前創建核心轉儲的設置:

ulimit -c

如果它輸出 unlimited,那么它使用的是(建議的)默認值。否則,用以下方法糾正限制:

ulimit -c unlimited

要禁用創建核心轉儲,可以設置其大小為 0:

ulimit -c 0

這個數字指定了核心轉儲文件的大小,單位是塊。

什么是核心轉儲?

內核處理核心轉儲的方式定義在:

/proc/sys/kernel/core_pattern

我運行的是 Fedora 31,在我的系統上,該文件包含的內容是:

/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

這表明核心轉儲被轉發到 systemd-coredump 工具。在不同的 Linux 發行版中,core_pattern 的內容會有很大的不同。當使用 systemd-coredump 時,轉儲文件被壓縮保存在 /var/lib/systemd/coredump 下。你不需要直接接觸這些文件,你可以使用 coredumpctl。比如說:

coredumpctl list

會顯示系統中保存的所有可用的轉儲文件。

使用 coredumpctl dump,你可以從最后保存的轉儲文件中檢索信息:

[stephan@localhost core_dump_example]$ ./coredump  Application started… (…….) Message: Process 4598 (coredump) of user 1000 dumped core. Stack trace of thread 4598: #0 0x00007f4bbaf22625 __GI_raise (libc.so.6) #1 0x00007f4bbaf0b8d9 __GI_abort (libc.so.6) #2 0x00007f4bbaf664af __libc_message (libc.so.6) #3 0x00007f4bbaf6da9c malloc_printerr (libc.so.6) #4 0x00007f4bbaf6f49c _int_free (libc.so.6) #5 0x000000000040120e n/a (/home/stephan/Dokumente/core_dump_example/coredump) #6 0x00000000004013b1 n/a (/home/stephan/Dokumente/core_dump_example/coredump) #7 0x00007f4bbaf0d1a3 __libc_start_main (libc.so.6) #8 0x000000000040113e n/a (/home/stephan/Dokumente/core_dump_example/coredump) Refusing to dump core to tty (use shell redirection or specify?—?output).

這表明該進程被 SIGABRT 停止。這個視圖中的堆棧跟蹤不是很詳細,因為它不包括函數名。然而,使用 coredumpctl debug,你可以簡單地用調試器(默認為 GDB)打開轉儲文件。輸入 bt(回溯backtrace的縮寫)可以得到更詳細的視圖:

Core was generated by `./coredump -c1'. Program terminated with signal SIGABRT, Aborted. #0  __GI_raise (sigsig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 50  return ret; (gdb) bt #0  __GI_raise (sigsig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 #1  0x00007fc37a9aa8d9 in __GI_abort () at abort.c:79 #2  0x00007fc37aa054af in __libc_message (actionaction=action@entry=do_abort, fmtfmt=fmt@entry=0x7fc37ab14f4b "%s\n") at ../sysdeps/posix/libc_fatal.c:181 #3  0x00007fc37aa0ca9c in malloc_printerr (strstr=str@entry=0x7fc37ab130e0 "free(): invalid pointer") at malloc.c:5339 #4  0x00007fc37aa0e49c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173 #5  0x000000000040120e in freeSomething(void*) () #6  0x0000000000401401 in main ()

與后續幀相比,main() 和 freeSomething() 的內存地址相當低。由于共享對象被映射到虛擬地址空間末尾的區域,可以認為 SIGABRT 是由共享庫中的調用引起的。共享對象的內存地址在多次調用之間并不是恒定不變的,所以當你看到多次調用之間的地址不同時,完全可以認為是共享對象。

堆棧跟蹤顯示,后續的調用源于 malloc.c,這說明內存的(取消)分配可能出了問題。

在源代碼中,(即使沒有任何 C++ 知識)你也可以看到,它試圖釋放一個指針,而這個指針并沒有被內存管理函數返回。這導致了未定義的行為,并導致了 SIGABRT。

void freeSomething(void *ptr){     free(ptr); } int nTmp = 5; int *ptrNull = &nTmp; freeSomething(ptrNull);

systemd 的這個 coredump 工具可以在 /etc/systemd/coredump.conf 中配置??梢栽?/etc/systemd/systemd-tmpfiles-clean.timer 中配置輪換清理轉儲文件。

你可以在其手冊頁中找到更多關于 coredumpctl 的信息。

用調試符號編譯

打開 Makefile 并注釋掉第 9 行的最后一部分?,F在應該是這樣的:

CFLAGS =-Wall -Werror -std=c++11 -g

-g 開關使編譯器能夠創建調試信息。啟動應用程序,這次使用 -c2 開關。

./coredump -c2

你會得到一個浮點異常。在 GDB 中打開該轉儲文件:

coredumpctl debug

這一次,你會直接被指向源代碼中導致錯誤的那一行:

Reading symbols from /home/stephan/Dokumente/core_dump_example/coredump… [New LWP 6218] Core was generated by `./coredump -c2'. Program terminated with signal SIGFPE, Arithmetic exception. #0 0x0000000000401233 in zeroDivide () at main.cpp:29 29 nRes = 5 / nDivider; (gdb)

鍵入 list 以獲得更好的源代碼概覽:

(gdb) list 24      int zeroDivide(){ 25          int nDivider = 5; 26          int nRes = 0; 27          while(nDivider > 0){ 28              nDivider--; 29              nRes = 5 / nDivider; 30          } 31          return nRes; 32      }

使用命令 info locals 從應用程序失敗的時間點檢索局部變量的值:

(gdb) info locals nDivider = 0 nRes = 5

結合源碼,可以看出,你遇到的是零除錯誤:

nRes = 5 / 0

結論

了解如何處理轉儲文件將幫助你找到并修復應用程序中難以重現的隨機錯誤。而如果不是你的應用程序,將核心轉儲轉發給開發人員將幫助她或他找到并修復問題。

到此,關于“怎么在Linux上創建并調試轉儲文件”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女