www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 嵌入式 > 嵌入式軟件
[導讀]本周工作中,我花了整整一周的時間來嘗試調(diào)試一個段錯誤。我以前從來沒有這樣做過,我花了很長時間才弄清楚其中涉及的一些基本事情(獲得核心轉(zhuǎn)儲、找到導致段錯誤的行號)。于是便有了這篇博客來解釋如何做那些事情! 在看完這篇博客后,你應(yīng)該知道如何從“哦,我的程序出現(xiàn)段錯誤,但我不知道正在發(fā)生什么”到“我知道它出現(xiàn)段錯誤時的堆棧、行號了! ”。

本周工作中,我花了整整一周的時間來嘗試調(diào)試一個段錯誤。我以前從來沒有這樣做過,我花了很長時間才弄清楚其中涉及的一些基本事情(獲得核心轉(zhuǎn)儲、找到導致段錯誤的行號)。于是便有了這篇博客來解釋如何做那些事情!

在看完這篇博客后,你應(yīng)該知道如何從“哦,我的程序出現(xiàn)段錯誤,但我不知道正在發(fā)生什么”到“我知道它出現(xiàn)段錯誤時的堆棧、行號了! ”。

什么是段錯誤?

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

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

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

一個已被破壞并且指向錯誤的地方的 C++ 虛表指針C++ vtable pointer,這導致程序嘗試執(zhí)行沒有執(zhí)行權(quán)限的內(nèi)存中的指令;

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

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

但是!這篇博客后不是關(guān)于 C++ 問題的。讓我們談?wù)摰幕镜臇|西,比如,我們?nèi)绾蔚玫揭粋€核心轉(zhuǎn)儲?

步驟1:運行 valgrind

我發(fā)現(xiàn)找出為什么我的程序出現(xiàn)段錯誤的最簡單的方式是使用 valgrind:我運行

valgrind -v your-program

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

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

如何獲得一個核心轉(zhuǎn)儲

核心轉(zhuǎn)儲core dump是您的程序內(nèi)存的一個副本,并且當您試圖調(diào)試您的有問題的程序哪里出錯的時候它非常有用。

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

這就是我最終做的事情:

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

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

ulimit:設(shè)置核心轉(zhuǎn)儲的最大尺寸

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

例如這些是我的系統(tǒng)上一個隨便一個 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

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

kernel.core_pattern:核心轉(zhuǎn)儲保存在哪里

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

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

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

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

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

kernel.core_pattern 和 Ubuntu

默認情況下在 ubuntu 系統(tǒng)中,kernel.core_pattern 被設(shè)置為下面的值:

$ sysctl kernel.core_pattern

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

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

Ubuntu 使用一種叫做 apport 的系統(tǒng)來報告 apt 包有關(guān)的崩潰信息。

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

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

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

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

現(xiàn)在你有了核心轉(zhuǎn)儲,接下來干什么?

好的,現(xiàn)在我們了解了 ulimit 和 kernel.core_pattern ,并且實際上在磁盤的 /tmp 目錄中有了一個核心轉(zhuǎn)儲文件。太好了!接下來干什么?我們?nèi)匀徊恢涝摮绦驗槭裁磿霈F(xiàn)段錯誤!

下一步將使用 gdb 打開核心轉(zhuǎn)儲文件并獲取堆棧調(diào)用序列。

從 gdb 中得到堆棧調(diào)用序列

你可以像這樣用 gdb 打開一個核心轉(zhuǎn)儲文件:

$ gdb -c my_core_file

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

下面是如何加載調(diào)試符號。

symbol-file /path/to/my/binary

sharedlibrary

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

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

查看每個線程的堆棧

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

thread apply all bt full

gdb + 核心轉(zhuǎn)儲 = 驚喜

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

如果您仍然正在基于 gdb 向?qū)砉ぷ魃?,只打印出棧跟蹤與bt也可以。 :)

ASAN

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

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

從一個核心轉(zhuǎn)儲得到一個堆棧跟蹤真的很親切!

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

試試用 valgrind

如果那沒用,或者你想要拿到一個核心轉(zhuǎn)儲來調(diào)查:

確保二進制文件編譯時帶有調(diào)試符號信息;

正確的設(shè)置 ulimit 和 kernel.core_pattern;

運行程序;

一旦你用 gdb 調(diào)試核心轉(zhuǎn)儲了,加載符號并運行 bt;

嘗試找出發(fā)生了什么!

我可以使用 gdb 弄清楚有個 C++ 的虛表條目指向一些被破壞的內(nèi)存,這有點幫助,并且使我感覺好像更懂了 C++ 一點。也許有一天我們會更多地討論如何使用 gdb 來查找問題!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

阿聯(lián)酋迪拜2025年8月26日 /美通社/ -- 納斯達克上市公司Robo.ai Inc.今日正式宣布完成品牌煥新升級,并于8月26日正式啟用全新納斯達克股票代碼"...

關(guān)鍵字: AI 人工智能 代碼 智能科技

CPU親和度通過限制進程或線程可以運行的CPU核心集合,使得它們只能在指定的CPU核心上執(zhí)行。這可以減少CPU緩存的失效次數(shù),提高緩存命中率,從而提升系統(tǒng)性能。

關(guān)鍵字: Linux 嵌入式

北京2025年8月13日 /美通社/ -- 近日,北京積算科技有限公司(以下簡稱"積算科技")推出一站式AlphaFold3在線算力服務(wù),現(xiàn)已開放免費使用。其內(nèi)置優(yōu)化后的AlphaFold3模型,支持...

關(guān)鍵字: ALPHA 代碼 圖形化 蛋白質(zhì)

在Linux系統(tǒng)性能優(yōu)化中,內(nèi)存管理與網(wǎng)絡(luò)連接處理是兩大核心領(lǐng)域。vm.swappiness與net.core.somaxconn作為關(guān)鍵內(nèi)核參數(shù),直接影響系統(tǒng)在高負載場景下的穩(wěn)定性與響應(yīng)速度。本文通過實戰(zhàn)案例解析這兩個...

關(guān)鍵字: Linux 內(nèi)存管理

Zephyr開源項目由Linux基金會維護,是一個針對資源受限的嵌入式設(shè)備優(yōu)化的小型、可縮放、多體系結(jié)構(gòu)實時操作系統(tǒng)(RTOS)。近年來,Zephyr RTOS在嵌入式開發(fā)中的采用度逐步增加,支持的開發(fā)板和傳感器不斷增加...

關(guān)鍵字: 嵌入式系統(tǒng) 軟件開發(fā) 實時操作系統(tǒng) Zephyr項目

對于LLM,我使用b谷歌Gemini的免費層,所以唯一的成本是n8n托管。在使用了n8n Cloud的免費積分后,我決定將其托管在Railway上(5美元/月)。然而,由于n8n是開源的,您可以在自己的服務(wù)器上托管它,而...

關(guān)鍵字: 人工智能 n8n Linux

北京2025年7月21日 /美通社/ -- 浪潮信息宣布元腦企智一體機已率先完成對Kimi K2 萬億參數(shù)大模型的適配支持,并實現(xiàn)單用戶70 tokens/s的流暢輸出速度,為企業(yè)客戶高效部署應(yīng)用大模型提供高處...

關(guān)鍵字: 模型 AGENT TOKEN 代碼

在Linux系統(tǒng)管理中,權(quán)限控制是安全運維的核心。本文通過解析/etc/sudoers文件配置與組策略的深度應(yīng)用,結(jié)合某金融企業(yè)生產(chǎn)環(huán)境案例(成功攔截98.7%的非法提權(quán)嘗試),揭示精細化權(quán)限管理的關(guān)鍵技術(shù)點,包括命令別...

關(guān)鍵字: Linux 用戶權(quán)限 sudoers文件

Linux內(nèi)核中的信號量(Semaphore)是一種用于資源管理的同步原語,它允許多個進程或線程對共享資源進行訪問控制。信號量的主要作用是限制對共享資源的并發(fā)訪問數(shù)量,從而防止系統(tǒng)過載和數(shù)據(jù)不一致的問題。

關(guān)鍵字: Linux 嵌入式

在云計算與容器化技術(shù)蓬勃發(fā)展的今天,Linux網(wǎng)絡(luò)命名空間(Network Namespace)已成為構(gòu)建輕量級虛擬網(wǎng)絡(luò)的核心組件。某頭部互聯(lián)網(wǎng)企業(yè)通過命名空間技術(shù)將測試環(huán)境資源消耗降低75%,故障隔離效率提升90%。本...

關(guān)鍵字: Linux 云計算
關(guān)閉