欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學堂Linux開發(fā)解析如何得到一個段錯誤的核心轉(zhuǎn)儲

2018-07-19 11:23:43 1549瀏覽

在現(xiàn)如今,大多數(shù)程序開發(fā)都會涉及到程序調(diào)試一個段錯誤,比如在Linux開發(fā)培訓中,如何得到一個段錯誤的核心轉(zhuǎn)儲呢?下面我們一起來看一下吧。



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

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

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

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

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

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

但是!這篇博客后不是關于C++問題的。讓我們談論的基本的東西,比如,我們?nèi)绾蔚玫揭粋€核心轉(zhuǎn)儲?

步驟1:運行valgrind

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

valgrind-vyour-program

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

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

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

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

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

這就是最終做的事情:

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

運行sudosysctl-wkernel.core_pattern=/tmp/core-%e.%p.%h.%t

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

ulimit-c設置核心轉(zhuǎn)儲的最大尺寸。它往往設置為0,這意味著內(nèi)核根本不會寫核心轉(zhuǎn)儲。它以千字節(jié)為單位。ulimit是按每個進程分別設置的——你可以通過運行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)儲文件時使用軟限制softlimit(在這種情況下,maxcorefilesize=0)。您可以使用shell內(nèi)置命令ulimit(ulimit-cunlimited)將軟限制增加到硬限制hardlimit。

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

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

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

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

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

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

kernel.core_pattern和Ubuntu

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

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

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

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

設定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重新設置為sysctl-wkernel.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-cmy_core_file

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

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

symbol-file/path/to/my/binary

sharedlibrary

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

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

查看每個線程的堆棧

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

threadapplyallbtfull

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

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

如果您仍然正在基于gdb向?qū)砉ぷ魃希淮蛴〕鰲8櫯cbt也可以。:)

ASAN

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

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

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

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

試試用valgrind

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

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

正確的設置ulimit和kernel.core_pattern;

運行程序;

一旦你用gdb調(diào)試核心轉(zhuǎn)儲了,加載符號并運行bt;可以使用gdb弄清楚有個C++的虛表條目指向一些被破壞的內(nèi)存。

以上就是關于扣丁學堂Linux開發(fā)解析如何得到一個段錯誤核心轉(zhuǎn)儲的詳細介紹,希望對小伙伴們能有所幫助,想要了解更多關于Linux開發(fā)方面內(nèi)容的小伙伴可以登錄扣丁學堂官網(wǎng)咨詢??鄱W堂有專業(yè)的Linux培訓班供想要學習Linux開發(fā)技術的小伙伴學習,此外扣丁學堂還有大量的Linux視頻教程和與時俱進的課程體系,想要學習Linux的小伙伴快到扣丁學堂報名吧??鄱W堂Linux技術交流群:422345477。

扣丁學堂微信公眾號



關注微信公眾號獲取更多的學習資料



查看更多關于“Linux培訓資訊”的相關文章>>

標簽:

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部