中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

在Linux上怎么得到一個段錯誤的核心轉儲

發布時間:2021-10-23 09:27:48 來源:億速云 閱讀:141 作者:小新 欄目:系統運維

這篇文章主要介紹了在Linux上怎么得到一個段錯誤的核心轉儲,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

什么是段錯誤?

段錯誤segmentation fault”是指你的程序嘗試訪問不允許訪問的內存地址的情況。這可能是由于:

  • 試圖解引用空指針(你不被允許訪問內存地址 0);

  • 試圖解引用其他一些不在你內存(LCTT 譯注:指不在合法的內存地址區間內)中的指針;

  • 一個已被破壞并且指向錯誤的地方的

    C++ 虛表指針C++ vtable pointer

    ,這導致程序嘗試執行沒有執行權限的內存中的指令;

  • 其他一些我不明白的事情,比如我認為訪問未對齊的內存地址也可能會導致段錯誤(LCTT 譯注:在要求自然邊界對齊的體系結構,如 MIPS、ARM 中更容易因非對齊訪問產生段錯誤)。

這個“C++ 虛表指針”是我的程序發生段錯誤的情況。我可能會在未來的博客中解釋這個,因為我最初并不知道任何關于 C++ 的知識,并且這種虛表查找導致程序段錯誤的情況也是我所不了解的。

但是!這篇博客后不是關于 C++ 問題的。讓我們談論的基本的東西,比如,我們如何得到一個核心轉儲?

步驟1:運行 valgrind

我發現找出為什么我的程序出現段錯誤的最簡單的方式是使用 valgrind:我運行

valgrind -v your-program

這給了我一個故障時的堆棧調用序列。 簡潔!

但我想也希望做一個更深入調查,并找出些 valgrind 沒告訴我的信息! 所以我想獲得一個核心轉儲并探索它。

如何獲得一個核心轉儲

核心轉儲core dump是您的程序內存的一個副本,并且當您試圖調試您的有問題的程序哪里出錯的時候它非常有用。

當您的程序出現段錯誤,Linux 的內核有時會把一個核心轉儲寫到磁盤。 當我最初試圖獲得一個核心轉儲時,我很長一段時間非常沮喪,因為 - Linux 沒有生成核心轉儲!我的核心轉儲在哪里?

這就是我最終做的事情:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 在啟動我的程序之前運行 ulimit -c unlimited

  3. 運行 sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t

ulimit:設置核心轉儲的***尺寸

ulimit -c 設置核心轉儲的***尺寸。 它往往設置為 0,這意味著內核根本不會寫核心轉儲。 它以千字節為單位。 ulimit 是按每個進程分別設置的 —— 你可以通過運行 cat /proc/PID/limit 看到一個進程的各種資源限制。

例如這些是我的系統上一個隨便一個 Firefox 進程的資源限制:

$ cat /proc/6309/limits Limit                     Soft Limit           Hard Limit           Units     Max cpu time              unlimited            unlimited            seconds   Max file size             unlimited            unlimited            bytes     Max data size             unlimited            unlimited            bytes     Max stack size            8388608              unlimited            bytes     Max core file size        0                    unlimited            bytes     Max resident set          unlimited            unlimited            bytes     Max processes             30571                30571                processes Max open files            1024                 1048576              files     Max locked memory         65536                65536                bytes     Max address space         unlimited            unlimited            bytes     Max file locks            unlimited            unlimited            locks     Max pending signals       30571                30571                signals   Max msgqueue size         819200               819200               bytes     Max nice priority         0                    0                    Max realtime priority     0                    0                    Max realtime timeout      unlimited            unlimited            us

內核在決定寫入多大的核心轉儲文件時使用軟限制soft limit(在這種情況下,max core file size = 0)。 您可以使用 shell 內置命令 ulimitulimit -c unlimited) 將軟限制增加到硬限制hard limit

kernel.core_pattern:核心轉儲保存在哪里

kernel.core_pattern 是一個內核參數,或者叫 “sysctl 設置”,它控制 Linux 內核將核心轉儲文件寫到磁盤的哪里。

內核參數是一種設定您的系統全局設置的方法。您可以通過運行 sysctl -a 得到一個包含每個內核參數的列表,或使用 sysctl kernel.core_pattern 來專門查看 kernel.core_pattern 設置。

所以 sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t 將核心轉儲保存到目錄 /tmp 下,并以 core 加上一系列能夠標識(出故障的)進程的參數構成的后綴為文件名。

如果你想知道這些形如 %e%p 的參數都表示什么,請參考 man core。

有一點很重要,kernel.core_pattern 是一個全局設置 —— 修改它的時候***小心一點,因為有可能其它系統功能依賴于把它被設置為一個特定的方式(才能正常工作)。

kernel.core_pattern 和 Ubuntu

默認情況下在 ubuntu 系統中,kernel.core_pattern 被設置為下面的值:

$ sysctl kernel.core_patternkernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P

這引起了我的迷惑(這 apport 是干什么的,它對我的核心轉儲做了什么?)。以下關于這個我了解到的:

  • Ubuntu 使用一種叫做 apport 的系統來報告 apt 包有關的崩潰信息。

  • 設定 kernel.core_pattern=|/usr/share/apport/apport %p %s %c %d %P 意味著核心轉儲將被通過管道送給 apport 程序。

  • apport 的日志保存在文件 /var/log/apport.log 中。

  • apport 默認會忽略來自不屬于 Ubuntu 軟件包一部分的二進制文件的崩潰信息

我最終只是跳過了 apport,并把 kernel.core_pattern 重新設置為 sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t,因為我在一臺開發機上,我不在乎 apport 是否工作,我也不想嘗試讓 apport 把我的核心轉儲留在磁盤上。

現在你有了核心轉儲,接下來干什么?

好的,現在我們了解了 ulimitkernel.core_pattern ,并且實際上在磁盤的 /tmp 目錄中有了一個核心轉儲文件。太好了!接下來干什么?我們仍然不知道該程序為什么會出現段錯誤!

下一步將使用 gdb 打開核心轉儲文件并獲取堆棧調用序列。

從 gdb 中得到堆棧調用序列

你可以像這樣用 gdb 打開一個核心轉儲文件:

$ gdb -c my_core_file

接下來,我們想知道程序崩潰時的堆棧是什么樣的。在 gdb 提示符下運行 bt 會給你一個調用序列backtrace。在我的例子里,gdb 沒有為二進制文件加載符號信息,所以這些函數名就像 “??????”。幸運的是,(我們通過)加載符號修復了它。

下面是如何加載調試符號。

symbol-file /path/to/my/binarysharedlibrary

這從二進制文件及其引用的任何共享庫中加載符號。一旦我這樣做了,當我執行 bt 時,gdb 給了我一個帶有行號的漂亮的堆棧跟蹤!

如果你想它能工作,二進制文件應該以帶有調試符號信息的方式被編譯。在試圖找出程序崩潰的原因時,堆棧跟蹤中的行號非常有幫助。:)

查看每個線程的堆棧

通過以下方式在 gdb 中獲取每個線程的調用棧!

thread apply all bt full

gdb + 核心轉儲 = 驚喜

如果你有一個帶調試符號的核心轉儲以及 gdb,那太棒了!您可以上下查看調用堆棧(LCTT 譯注:指跳進調用序列不同的函數中以便于查看局部變量),打印變量,并查看內存來得知發生了什么。這是***的。

如果您仍然正在基于 gdb 向導來工作上,只打印出棧跟蹤與bt也可以。 :)

ASAN

另一種搞清楚您的段錯誤的方法是使用 AddressSanitizer 選項編譯程序(“ASAN”,即 $CC -fsanitize=address)然后運行它。 本文中我不準備討論那個,因為本文已經相當長了,并且在我的例子中打開 ASAN 后段錯誤消失了,可能是因為 ASAN 使用了一個不同的內存分配器(系統內存分配器,而不是 tcmalloc)。

在未來如果我能讓 ASAN 工作,我可能會多寫點有關它的東西。(LCTT 譯注:這里指使用 ASAN 也能復現段錯誤)

從一個核心轉儲得到一個堆棧跟蹤真的很親切!

聽起來很多,當我做這些的時候很困惑,但說真的,從一個段錯誤的程序中獲得一個堆棧調用序列不需要那么多步驟:

  1. 試試用 valgrind

如果那沒用,或者你想要拿到一個核心轉儲來調查:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 確保二進制文件編譯時帶有調試符號信息;

  3. 正確的設置 ulimitkernel.core_pattern

  4. 運行程序;

  5. 一旦你用 gdb 調試核心轉儲了,加載符號并運行 bt

  6. 嘗試找出發生了什么!

感謝你能夠認真閱讀完這篇文章,希望小編分享的“在Linux上怎么得到一個段錯誤的核心轉儲”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

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

AI

永和县| 岳阳县| 太保市| 三明市| 应用必备| 榆林市| 齐齐哈尔市| 屏东县| 星子县| 永胜县| 静安区| 海宁市| 治县。| 册亨县| 改则县| 抚远县| 安福县| 新密市| 南昌县| 湖口县| 东辽县| 丰城市| 富锦市| 麦盖提县| 二手房| 蒙自县| 定陶县| 营口市| 晋城| 安宁市| 永安市| 阿瓦提县| 南昌县| 台东县| 通河县| 纳雍县| 邮箱| 荥阳市| 南木林县| 浙江省| 揭阳市|