欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux平臺(tái)Segmentation fault(段錯(cuò)誤)調(diào)試過程

 更新時(shí)間:2023年09月04日 09:40:08   作者:good-destiny  
這篇文章主要介紹了Linux平臺(tái)Segmentation fault(段錯(cuò)誤)調(diào)試過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1. 段錯(cuò)誤是什么

一句話來說,段錯(cuò)誤是指訪問的內(nèi)存超出了系統(tǒng)給這個(gè)程序所設(shè)定的內(nèi)存空間,

例如訪問了不存在的內(nèi)存地址、訪問了系統(tǒng)保護(hù)的內(nèi)存地址、訪問了只讀的內(nèi)存地址等等情況。

2. 段錯(cuò)誤的原因

段錯(cuò)誤,英文segmentation fault

段錯(cuò)誤的定義 

segementation fault (often shortened to segfault) or access violation
often raised by hardware with memory protection, notifying an operation system(OS) the software has attempted to access a restricted area of memory.

段錯(cuò)誤常見于提供低級(jí)別的內(nèi)存訪問機(jī)制(如C語言)的語言程序中,通常由非法訪問導(dǎo)致,即錯(cuò)誤地使用指針訪問虛擬內(nèi)存。

原因列舉

  • 對(duì)空指針賦值——由內(nèi)存管理硬件所導(dǎo)致
  • 嘗試去訪問一個(gè)不存在的內(nèi)存地址(超出進(jìn)程分配的地址)
  • 嘗試去訪問程序無權(quán)限訪問的地址(如進(jìn)程上下文中的內(nèi)核結(jié)構(gòu)(kernel structures))
  • 嘗試去訪問只讀的內(nèi)存(如代碼段)

對(duì)應(yīng)著程序中的情況分別為:

  • 引用或者賦值一個(gè)為初始化的指針(野指針(wild pointer),隨機(jī)指向一個(gè)內(nèi)存地址)
  • 引用或者賦值一個(gè)已經(jīng)被free的指針(dangling pointer,指向一個(gè)已經(jīng)被freed/deallocated/deleted的內(nèi)存地址)
  • A buffer overflow
  • A stack overflow

3. 段錯(cuò)誤信息的獲取

3.1 dmesg

dmesg可以在應(yīng)用程序crash掉時(shí),顯示內(nèi)核中保存的相關(guān)信息。

如下所示,通過dmesg命令可以查看發(fā)生段錯(cuò)誤的程序名稱、引起段錯(cuò)誤發(fā)生的內(nèi)存地址、指令指針地址、堆棧指針地址、錯(cuò)誤代碼、錯(cuò)誤原因等。

3.2 -g

使用gcc編譯程序的源碼時(shí),加上-g參數(shù),這樣可以使得生成的二進(jìn)制文件中加入可以用于gdb調(diào)試的有用信息。

3.3 nm

使用nm命令列出二進(jìn)制文件中的符號(hào)表,包括符號(hào)地址、符號(hào)類型、符號(hào)名等,這樣可以幫助定位在哪里發(fā)生了段錯(cuò)誤。

3.4 ldd

使用ldd命令查看二進(jìn)制程序的共享鏈接庫依賴,包括庫的名稱、起始地址,這樣可以確定段錯(cuò)誤到底是發(fā)生在了自己的程序中還是依賴的共享庫中。

4. 段錯(cuò)誤的調(diào)試方法

4.1 使用gcc和gdb

4.1.1 調(diào)試步驟

為了能夠使用gdb調(diào)試程序,在編譯階段加上-g參數(shù),以程序segfault3.c為例。

root@twq2018:~/segfault$ gcc -g -o segfault3 segfault3.c
root@twq2018:~/segfault$ gdb ./segfault3
(gdb) run
Starting program: /home/twq/segfault/segfault3 
Program received signal SIGSEGV, Segmentation fault.
0x001a306a in memcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb)

從輸出看出,程序segfault3.c收到SIGSEGV信號(hào),觸發(fā)段錯(cuò)誤,并提示地址0x001a306a、調(diào)用memcpy報(bào)的錯(cuò),位于/lib/tls/i686/cmov/libc.so.6庫中。

4.1.2 適用場景

1、僅當(dāng)能確定程序一定會(huì)發(fā)生段錯(cuò)誤的情況下使用。

2、當(dāng)程序的源碼可以獲得的情況下,使用-g參數(shù)編譯程序。

3、一般用于測試階段,生產(chǎn)環(huán)境下gdb會(huì)有副作用:使程序運(yùn)行減慢,運(yùn)行不夠穩(wěn)定,等等。

4、即使在測試階段,如果程序過于復(fù)雜,gdb也不能處理。

4.2 使用gdb和core文件

在4.1節(jié)中提到段錯(cuò)誤會(huì)觸發(fā)SIGSEGV信號(hào),通過man 7 signal,可以看到SIGSEGV默認(rèn)的handler會(huì)打印段錯(cuò)誤出錯(cuò)信息,并產(chǎn)生core文件,由此我們可以借助于程序異常退出時(shí)生成的core文件中的調(diào)試信息。

使用gdb工具來調(diào)試程序中的段錯(cuò)誤,用bt命令查看backtrace以檢查發(fā)生程序運(yùn)行到哪里, 來定位core dump的文件->行.。

4.2.1 調(diào)試步驟

1、在一些Linux版本下,默認(rèn)是不產(chǎn)生core文件的,首先可以查看一下系統(tǒng)core文件的大小限制:

root@twq2018:~/segfault$ ulimit -c
0

2、可以看到默認(rèn)設(shè)置情況下,本機(jī)Linux環(huán)境下發(fā)生段錯(cuò)誤時(shí)不會(huì)自動(dòng)生成core文件,下面設(shè)置下core文件的大小限制(單位為KB),其中使用ulimit  -c unlimited來設(shè)置無限大,則任意情況下都會(huì)產(chǎn)生core文件。

root@twq2018:~/segfault$ ulimit -c 1024
root@twq2018:~/segfault$ ulimit -c
1024

3、運(yùn)行程序segfault3.c,發(fā)生段錯(cuò)誤生成core文件:

root@twq2018:~/segfault$ ./segfault3
段錯(cuò)誤 (core dumped) 

4、加載core文件,使用gdb工具進(jìn)行調(diào)試:

root@twq2018:~/segfault$ gdb ./segfault3 ./core 

4.2.2 適用場景

1、適合于在實(shí)際生成環(huán)境下調(diào)試程序的段錯(cuò)誤(即在不用重新發(fā)生段錯(cuò)誤的情況下重現(xiàn)段錯(cuò)誤)。

2、當(dāng)程序很復(fù)雜,core文件相當(dāng)大時(shí),該方法不可用。

4.3 使用objdump

4.3.1 調(diào)試步驟

1、使用dmesg命令,找到最近發(fā)生的段錯(cuò)誤輸出信息:

root@twq2018:~/segfault$ dmesg
... ...
[17257.502808] segfault3[3320]: segfault at 80484e0 ip 0018506a sp bfc1cd6c error 7 in libc-2.10.1.so[110000+13e000]

其中,對(duì)我們接下來的調(diào)試過程有用的是發(fā)生段錯(cuò)誤的地址:80484e0和指令指針地址:0018506a。

2、使用objdump生成二進(jìn)制的相關(guān)信息,重定向到文件中:

root@twq2018:~/segfault$ objdump -d ./segfault3 > segfault3Dump

其中,生成的segfault3Dump文件中包含了二進(jìn)制文件的segfault3的匯編代碼。

3、在segfault3Dump文件中查找發(fā)生段錯(cuò)誤的地址:

root@twq2018:~/segfault$ grep -n -A 10 -B 10 "80484e0" ./segfault3Dump 
121- 80483df:    ff d0                    call   *%eax
122- 80483e1:    c9                       leave  
123- 80483e2:    c3                       ret    
124- 80483e3:    90                       nop
125-
126-080483e4 <main>:
127- 80483e4:    55                       push   %ebp
128- 80483e5:    89 e5                    mov    %esp,%ebp
129- 80483e7:    83 e4 f0                 and    $0xfffffff0,%esp
130- 80483ea:    83 ec 20                 sub    $0x20,%esp
131: 80483ed:    c7 44 24 1c e0 84 04     movl   $0x80484e0,0x1c(%esp)
132- 80483f4:    08 
133- 80483f5:    b8 e5 84 04 08           mov    $0x80484e5,%eax
134- 80483fa:    c7 44 24 08 05 00 00     movl   $0x5,0x8(%esp)
135- 8048401:    00 
136- 8048402:    89 44 24 04              mov    %eax,0x4(%esp)
137- 8048406:    8b 44 24 1c              mov    0x1c(%esp),%eax
138- 804840a:    89 04 24                 mov    %eax,(%esp)
139- 804840d:    e8 0a ff ff ff           call   804831c <memcpy@plt>
140- 8048412:    c9                       leave  
141- 8048413:    c3                       ret   

通過對(duì)以上匯編代碼分析,得知段錯(cuò)誤發(fā)生main函數(shù),對(duì)應(yīng)的匯編指令是movl $0x80484e0,0x1c(%esp),接下來打開程序的源碼,找到匯編指令對(duì)應(yīng)的源碼,也就定位到段錯(cuò)誤了。 

4.3.2 適用場景

1、不需要-g參數(shù)編譯,不需要借助于core文件,但需要有一定的匯編語言基礎(chǔ)。

2、如果使用了gcc編譯優(yōu)化參數(shù)(-O1,-O2,-O3)的話,生成的匯編指令將會(huì)被優(yōu)化,使得調(diào)試過程有些難度。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Linux進(jìn)程地址空間詳解

    Linux進(jìn)程地址空間詳解

    文章主要介紹了進(jìn)程地址空間和頁表的工作原理,以及它們在操作系統(tǒng)中的作用,通過父子進(jìn)程的示例,解釋了進(jìn)程地址空間的共享和獨(dú)立性,以及頁表如何將虛擬地址轉(zhuǎn)換為物理地址,文章還討論了頁表的其他功能,如權(quán)限控制和頁面置換算法,并簡要介紹了缺頁中斷的處理過程
    2025-02-02
  • Linux線程退出方式總結(jié)(推薦)

    Linux線程退出方式總結(jié)(推薦)

    下面小編就為大家?guī)硪黄狶inux線程退出方式總結(jié)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • 在Ubuntu20.04中安裝ROS Noetic的方法

    在Ubuntu20.04中安裝ROS Noetic的方法

    這篇文章主要介紹了在Ubuntu20.04中安裝ROS Noetic的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 詳解linux中nginx啟動(dòng) 重啟 關(guān)閉命令

    詳解linux中nginx啟動(dòng) 重啟 關(guān)閉命令

    本篇文章主要介紹了詳解linux中nginx啟動(dòng) 重啟 關(guān)閉命令,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • 詳解Linux下Tomcat開啟查看GC信息

    詳解Linux下Tomcat開啟查看GC信息

    這篇文章主要介紹了詳解Linux下Tomcat開啟查看GC信息,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • linux壓縮解壓文件夾命令zip unzip和tar詳解

    linux壓縮解壓文件夾命令zip unzip和tar詳解

    本文介紹了如何使用zip和unzip命令處理.zip文件,以及如何使用tar命令處理.tar、.tar.gz、.tar.bz2和.tar.xz文件,包括壓縮、解壓、查看壓縮包內(nèi)容、打包與壓縮、解壓到指定目錄、排除文件、遞歸壓縮和壓縮算法對(duì)比等內(nèi)容
    2025-02-02
  • CentOS 7.2安裝Zabbix 3.2教程詳解

    CentOS 7.2安裝Zabbix 3.2教程詳解

    這篇文章主要介紹了CentOS 7.2安裝Zabbix 3.2教程詳解的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • Linux、ubuntu系統(tǒng)下查看顯卡型號(hào)、顯卡信息詳解

    Linux、ubuntu系統(tǒng)下查看顯卡型號(hào)、顯卡信息詳解

    這篇文章主要介紹了如何在Linux、ubuntu系統(tǒng)下查看顯卡型號(hào)、顯卡信息的方法,需要的朋友可以參考下
    2022-04-04
  • CentOS 7中使用Squid提供HTTP代理詳解

    CentOS 7中使用Squid提供HTTP代理詳解

    這篇文章主要給大家介紹了在CentOS 7中使用Squid提供HTTP代理的相關(guān)資料,以及及客戶端的代理配置的方法,需要的朋友可以參考學(xué)習(xí),下面來一起看看吧。
    2017-04-04
  • Linux端口的開啟方式

    Linux端口的開啟方式

    文章主要介紹了在CentOS 7和CentOS 6系統(tǒng)中配置防火墻和iptables的步驟,包括查看、開啟、添加端口、重啟和重新加載防火墻等操作,并強(qiáng)調(diào)了在Linux中開啟端口后,遠(yuǎn)程telnet通常無法ping通的原因
    2024-12-12

最新評(píng)論