一.段錯誤產生的原因
段錯誤就是訪問了不可訪問的內存,出現(xiàn)了運行時出現(xiàn)了segmentation fault的報錯
產生的原因:訪問不存在的內存地址、訪問系統(tǒng)保護的內存地址 、訪問只讀的內存地址、空指針廢棄(eg:malloc與free釋放后,繼續(xù)使用)、堆棧溢出、內存越界(數(shù)組越界,變量類型不一致等)
二. 使用GDB逐步查找段錯誤
首先加上命令行得先加上-g -rdynamic的參數(shù)進行編譯,eg:gcc -g rdynamic xxx.c 隨著gdb ./a.out
eg:
運行結果很明顯,都不用一步步的調試,后面幾行就顯示了出錯位置。 并且進程還收到了SIGSEGV信號而結束,而SIGSEGV默認的handler的動作是打印“段錯誤”的出錯信息,并產生core文件。
三. 分析core文件
什么是core文件 Core文件其實就是內存的映像,當程序崩潰時,存儲內存的相應信息,主用用于對程序進行調試。 當程序崩潰時便會產生core文件,其實準確的應該說是core dump 文件,默認生成位置與可執(zhí)行程序位于同一目錄下,文件名為core. Core的意思是內存, Dump的意思是扔出來;core dump又叫核心轉儲, 當程序運行過程中發(fā)生異常, 程序異常退出時, 由操作系統(tǒng)把程序當前的內存狀況存儲在一個core文件中, 叫core dump.
如何使用
gdb-ccore文件路徑[應用程序的路徑] 1
進去后輸入where回車, 就可以顯示程序在哪一行當?shù)舻? 在哪個函數(shù)中。
但是core文件的生成跟你當前系統(tǒng)的環(huán)境設置有關系, 可以用下面的語句設置一下, 然后再運行程序便成生成core文件ulimit -c ulimited; 輸入命令
ulimit-c//查是否為0,是0就不生成core文件 ulimit-c1000//ulimit-culimited,改變數(shù)值,限制系統(tǒng)的core文件大小 12
eg
四.段錯誤時啟動調試
(gdb)bt二,三,四都是在基于系統(tǒng)上的gdb的前提進行的。如果沒有,glibc為我們提供了此類能夠dump棧內容的函數(shù)簇,詳見/usr/include/execinfo.h
五. 利用backtrace和objdump進行分析
eg
運行結果
這里得提一下,需要用到庫
運行結果似乎沒上面幾種方式的信息多,清晰;但是還沒完,我們再用objdump反匯編程序,找到上面地址對應的代碼位置。
objdump -d a.out找到對應main 0x5601a75e0b0f對應的代碼位置
backtrace函數(shù)
backtrace函數(shù)的作用:當程序出現(xiàn)異常,段錯誤,崩潰的情況下,會收到內核發(fā)送給進程的異常信號,會把程序的堆棧信息打印出來。
intbacktrace(void**buffer,intsize) //該函數(shù)獲取當前線程的調用堆棧,獲取的信息將會被存放在buffer中,它是一個指針數(shù)組,參數(shù)size用來指定buffer中可以保存多少個void*元素。函數(shù)的返回值是實際返回的void*元素個數(shù)。buffer中的void*元素實際是從堆棧中獲取的返回地址。 char**backtrace_symbols(void*const*buffer,intsize) //該函數(shù)將backtrace函數(shù)獲取的信息轉化為一個字符串數(shù)組,參數(shù)buffer是backtrace獲取的堆棧指針,size是backtrace返回值。函數(shù)返回值是一個指向字符串數(shù)組的指針,它包含char*元素個數(shù)為size。每個字符串包含了一個相對于buffer中對應元素的可打印信息,包括函數(shù)名、函數(shù)偏移地址和實際返回地址。 //backtrace_symbols生成的字符串占用的內存是malloc出來的,但是是一次性malloc出來的,釋放是只需要一次性釋放返回的二級指針即可。 voidbacktrace_symbols_fd(void*const*buffer,intsize,intfd) //該函數(shù)與backtrace_symbols函數(shù)功能相同,只是它不會malloc內存,而是將結果寫入文件描述符為fd的文件中,每個函數(shù)對應一行;該函數(shù)可重入。 1234567
注意事項:backtrace_symbols的實現(xiàn)需要符號名稱的支持,在gcc編譯過程中需要加入-rdynamic參數(shù);
objdump反匯編碼
objdump-ftest//顯示test的文件頭信息 objdump-dtest//反匯編test中的需要執(zhí)行指令的那些section objdump-Dtest//與-d類似,但反匯編test中的所有section objdump-htest//顯示test的SectionHeader信息 objdump-xtest//顯示test的全部Header信息 objdump-stest//除了顯示test的全部Header信息,還顯示他們對應的十六進制文件代碼 1234567891011
六.段錯誤信息的獲取
當我們運行的時候,發(fā)先有段錯誤segmentation fault時,我們可以通過一些命令進行段錯誤信息獲取。
-g gcc -g 主要適用于gdb調試
dmesg 直接輸入命令dmesgdmesg 可以在應用程序崩潰時,顯示內存中保存的相關信息。 dmesg 可以查看發(fā)生段錯誤的程序名稱、引起段錯誤發(fā)生的內存地址、指令指針地址、堆棧指針地址、錯誤代碼、錯誤原因等等。
ldd 命令
查看二進制程序的共享鏈接庫依賴,包括庫的名稱、起始地址,這樣可以確定段錯誤到底是發(fā)生在了自己的程序中還是依賴的共享庫中。
-
內存
+關注
關注
8文章
3064瀏覽量
74382 -
調試
+關注
關注
7文章
589瀏覽量
34082 -
文件
+關注
關注
1文章
571瀏覽量
24834 -
編譯
+關注
關注
0文章
662瀏覽量
33071 -
gdb
+關注
關注
0文章
60瀏覽量
13350
原文標題:段錯誤以及調試方法
文章出處:【微信號:技術讓夢想更偉大,微信公眾號:技術讓夢想更偉大】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
嵌入式C開發(fā)中段錯誤的3種調試方法
![嵌入式C開發(fā)中段<b class='flag-5'>錯誤</b>的3種<b class='flag-5'>調試</b><b class='flag-5'>方法</b>](https://file1.elecfans.com/web2/M00/8C/6F/wKgZomSstX6ABx_lAAAi2Ck4lD8748.png)
HardFault錯誤調試的定位方法是什么
網(wǎng)管配置通道環(huán)和復用段環(huán)方法
mplab icd3錯誤消息及解決方法
linux C用戶態(tài)調試追蹤函數(shù)調用堆棧以及定位段錯誤
![linux C用戶態(tài)<b class='flag-5'>調試</b>追蹤函數(shù)調用堆棧<b class='flag-5'>以及</b>定位<b class='flag-5'>段</b><b class='flag-5'>錯誤</b>](https://file.elecfans.com/web1/M00/91/FD/o4YBAFzdLwGAXUudAABjxOJ50LE953.png)
段錯誤調試神器 - Core Dump詳解
Linux環(huán)境下段錯誤的產生原因及調試方法小結
什么是段錯誤?
單片機硬錯誤排查方法
![單片機硬<b class='flag-5'>錯誤</b>排查<b class='flag-5'>方法</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論