天天看點

應用程式段錯誤調試1、段錯誤(SIGSEGV)的産生2、core檔案的産生3、使用gdb調試

1、段錯誤(SIGSEGV)的産生

  從使用者态程式開發的角度,我們并不需要了解作業系統複雜的記憶體管理機制,這是和硬體平台相關的。但是了解核心發送SIGSEGV信号的流程,對我們了解SIGSEGV是很有幫助的。

  

應用程式段錯誤調試1、段錯誤(SIGSEGV)的産生2、core檔案的産生3、使用gdb調試

  紅色部分展示了核心發送SIGSEGV 信号給使用者态程式的總體流程。當使用者态 程式通路一個會引發SIGSEGV 的位址時,硬體首先産生一個page fault,即“缺頁異常”。 在核心的page fault 處理函數中,首先判斷該位址是否屬于使用者态程式的位址空間。32位系統中虛拟存儲空間占4GB空間。Linux核心将這4G位元組的空間分為兩部分。使用者态程式的位址空間為[0x00000000,0xBFFFFFFF],核心位址空間為[0xC0000000,0xFFFFFFFF]。如果該位址屬于使用者态位址空間,檢查通路的類型是否和該記憶體區域的類型是否比對,不比對,則發送SIGSEGV 信号;如果該位址不屬于使用者态位址空間,檢查通路該位址的操作是否發生在使用者态,如果是,發送SIGSEGV 信号。 當程式不正常退出時,核心會在目前目錄産生core檔案(一個記憶體的映像,同時加上調試資訊),然後利用gdb檢視core檔案,可以訓示出導緻程式出錯位置的檔案和行數。

2、core檔案的産生

 2.1 系統配置

  确定系統是否配置支援dump core的功能。通過ulimit -c或ulimit -a,如果為0,則不會産生對應的coredump,需要進行修改和設定。使用 ulimit –c [size]這裡的size的機關是blocks,一般1block=512bytes在不知 size的大小的時候,可以ulimit -c unlimited。

 2.2 程式編譯

  1.用gcc(或者交叉編譯工具)進行編譯時,選擇-g選項。

  2.不能進行strip操作,否則你将看不見程式的函數名、變量名,代替這些将是運作時的記憶體位址。

 2.3 core的存儲位置

  core檔案預設的存儲位置與對應的可執行程式在同一目錄下,檔案名是core,大家可以通過下面的指令看到core檔案的存儲位置和格式:cat /proc/sys/kernel/core_pattern。

  其中core_pattern的格式見下面說明:

   %% 單個%字元

   %p 所dump程序的程序ID

   %u 所dump程序的實際使用者ID

   %g 所dump程序的實際組ID

   %s 導緻本次core dump的信号

   %t core dump的時間 (由1970年1月1日計起的秒數)

   %h 主機名

   %e 程式檔案名

   其中/proc/sys/kernel/core_uses_pid。如果這個檔案的内容被配置成1,即使core_pattern中沒有設定%p,最後生成的core dump檔案名仍會加上程序ID。以下是參數設定例子:

echo "1" > /proc/sys/kernel/core_uses_pid 
   sysctl -w kernel.core_uses_pid=;
   echo "/persistent/core-%e-%p-%t" > core_pattern;
   sysctl -w kernel.core_pattern=/persistent/core-%e-%p-%t
           

  注意:這裡是指在程序目前工作目錄的下建立。通常與程式在相同的路徑下。但如果程式中調用了chdir函數,則有可能改變了目前工作目錄。這時core檔案建立在chdir指定的路徑下。有好多程式崩潰了,我們卻找不到core檔案放在什麼位置。和chdir函數就有關系。當然程式崩潰了不一定都産生core檔案。

 2.4 什麼時候不産生core檔案

  ( a )程序是設定-使用者-ID,而且目前使用者并非程式檔案的所有者

  ( b )程序是設定-組-ID,而且目前使用者并非該程式檔案的組所有者

  ( c )使用者沒有寫目前工作目錄的許可權

  ( d )檔案太大。core檔案的許可權(假定該檔案在此之前并不存在)通常是使用者讀/,組讀和其他讀

  友情提醒:當環境當好後,可以使用在終端執行 “kill -11 應用程式PID”指令,然後檢視是否回生成core檔案。

3、使用gdb調試

  發生core dump之後, 用gdb進行檢視core檔案的内容, 以定位檔案中引發段錯誤的行。如下:

gdb [exec file] [core file]
如: arm-none-linux-gnueabi-gdb queuetest core
執行結果如下:
[email protected]:/home/lianxi# arm-none-linux-gnueabi-gdb queuetest core
GNU gdb (Sourcery G++ Lite q1-) -cvs
Copyright (C)  Free Software Foundation, Inc.
License GPLv3+: GNU GPL version  or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi".
For bug reporting instructions, please see:
<https://support.codesourcery.com/GNUToolchain/>...
Error while mapping shared library sections:
lib/libdl.so: No such file or directory.
Error while mapping shared library sections:
lib/libgcc_s.so: No such file or directory.
Error while mapping shared library sections:
lib/libc.so: No such file or directory.
Error while mapping shared library sections:
lib/ld-linux.so: No such file or directory.
Symbol file not found for /lib/libdl.so
Symbol file not found for /lib/libgcc_s.so
Symbol file not found for /lib/libc.so
Symbol file not found for /lib/ld-linux.so

warning: Unable to find dynamic linker.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Core was generated by `./queuetest'.
Program terminated with signal , Segmentation fault.
#   in main (argc=, argv=) at main.c:
      printf("ptr = %d\n", *ptr);
(gdb) where
#   in main (argc=, argv=) at main.c:
           

  gdb中鍵入where,就會看到程式崩潰時堆棧資訊(目前函數之前的所有已調用函數的清單),顯然錯誤出現main.c:38中。

  但往往調試沒這麼簡單,是以還得記住幾個常用的gdb指令,結合檢視分析

  bt 檢視堆棧資訊

  bt full 完全顯示函數之間互相調用時傳遞的參數值和函數的内部變量值

  where 顯示在哪兒down掉

  info locals 顯示目前的區域參數

  info threads 顯示目前可調試的所有線程,每個線程會有一個gdb為其配置設定的ID,後面操作線程的時候會用這個ID,前面有*的是目前調試的線程。

  thread id 切換目前調試的線程為指定ID的線程

  list 往下列出代碼

  info frame 檢視桢的詳細資訊

  thread apply all command 讓所有被調試線程執行gdb指令command

  x/nfu 檢視記憶體資訊

  注:在交叉編譯環境中,經常發現庫找不到的情況,這是因為沒有指定庫路徑的原因。可以通過以下兩個指令設定。

set solib-absolute-prefix 路徑
set solib-search-path  路徑
           

繼續閱讀