導航:首頁 > 文件教程 > 段錯誤沒生成core文件

段錯誤沒生成core文件

發布時間:2023-04-03 13:31:04

1. 段錯誤(core mped)」只知道跟資料庫 有關,但不知道如何解決,請高人幫忙解決此問題,

The problem that no `core' file is created on a segmentation fault; Locate errors in the source with GDB and `core' files
linux 程序在遇到段錯誤(常見的是由非法訪問內存引起)的時候會產生 core 文件,搜搜並如果這個程序包含調試信息(編譯的時候加 -g 選項),那麼使用 gdb 讀取這個 core 文件可以快速定位出錯的源代碼。原來在某軟體公司實習的時候(用 RedHat Enterprise Linux)覺得這樣非常方便查錯,但我自己用的 Debian GNU/Linux 卻默認不生成這個文件。
檢世跡查以後發現原因是 core 文件最大尺寸(用 ulimit -c 查看)是 0,把它設置成非 0 值就可以了,如:
ulimit -c 2048(設置 core 文件最大尺寸為 2048 blocks,1block=512bytes,因此這里設置的其實是 1MiB)
ulimit -c unlimited(不限 core 文件尺寸)
附:用 gdb 根據 core mp 文件定位錯誤的辦法。
用這個程序作一個測試:
int foo (int *p)
{
return *p;
}
main()
{
foo (0);
}
derek@dli: /tmp $ gcc -g a.c
derek@dli: /tmp $ ./a.out
段錯誤 (core mped)
derek@dli: /tmp $ gdb ./a.out -c core
(這里略去約十行其他信息)
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x0804834a in foo (p=0x0) at a.c:3
3 return *p;
如果再輸入一條命令 bt,就可以看得清清楚漏消楚錯誤是在什麼時機產生的:
(gdb) bt
#0 0x0804834a in foo (p=0x0) at a.c:3
#1 0x0804836b in main () at a.c:8
不能有比這更清楚的錯誤信息了!如果是在 Windows 下,就老老實實 Trace and Step 吧。

2. linux下終端運行文件,代碼沒有錯誤,為什麼出現段錯誤。

你代碼也沒有,調用堆棧也沒有,誰能知道為啥段錯誤啊,要不然你猜我今天穿什麼顏色的衣服?
大神也不敢說自己的代碼肯定就沒有錯誤,我猜你的意思是能正確編譯吧?
那隻能說明你的語法沒錯,僅此而已,寫程序能正確編譯只是第一步,後面調試的滑塌敗工作還很漫長。
下面說說怎麼調試吧:
看你的系統提示應該還沒有打開core輸出,在運行程序前打個命令:
ulimit -c unlimited
這樣設置之後再運行程序在段錯誤的時候能core mp,有core之後再gdb ./test core.xxx
core文件一般在你運行程序的目錄里,core文件後綴每次不同,後面的xxx你需要自衫蘆己看看文件名,一般是運行時的PID號。當然如果你的系統core的生成規則被改過,不是默認的,那就問你的系統管理員去找到core文件。
進去後打個bt,看下當前的調用堆棧,然後再看下哪兒出的問題。
當然這樣做有個前提,那就是你在編譯信顫你的程序時加了-g參數,如果沒有,重新去編譯下再運行。
如果還是找不出來,再把你的調用堆棧和代碼發上來大家看看。

3. linux c內存溢出的core mp bug怎麼跟

淺析Linux下core文件
當我們的程序崩潰時,內核有可能把該程序當前內存映射到core文件里,方便程序員找到程序出現問題的地方。最常出 現的,幾乎所有C程序員都出現過的錯誤就是「段錯誤」了。也是最難查出問題原因的一個錯誤。下面我們就針對「段錯誤」來分析core文件的產生、以及我們 如何利用core文件找到出現崩潰的地方。
何謂core文件
當一個程序崩潰時,在進程當前工作目錄的core文件中復制了該進程的存儲圖像。core文件僅僅是一個內存映象(同時加上調試信息),主要是用來調試的。
當程序接收到以下UNIX信號會產生core文件:

名字

說明

ANSI C POSIX.1

SVR4 4.3+BSD

預設動作

SIGABRT

異常終止(abort)

. .

. .

終止w/core

SIGBUS

硬體故障

.

. .

終止w/core

SIGEMT

硬體故障

. .

終止w/core

SIGFPE

算術異常

. .

. .

終止w/core

SIGILL

非法硬體指令

. .

. .

終止w/core

SIGIOT

硬體故障

. .

終止w/core

SIGQUIT

終端退出符

.

. .

終止w/core

SIGSEGV

無效存儲訪問

. .

. .

終止w/core

SIGSYS

無效系統調用

. .

終止w/core

SIGTRAP

硬體故障

. .

終止w/core

SIGXCPU

超過CPU限制(setrlimit)

. .

終止w/core

SIGXFSZ

超過文件長度限制(setrlimit)

. .

終止w/core

在系統默認動作列,「終止w/core」表示在進程當前工作目錄的core文件中復制了該進程的存儲圖像(該文件名為core,由此可以看出這種功能很久之前就是UNIX功能的一部分)。大多數UNIX調試程序都使用core文件以檢查進程在終止時的狀態。
core文件的產生不是POSIX.1所屬部分,而是很多UNIX版本的實現特徵。UNIX第6版沒有檢查條件 (a)和(b),並且其源代碼中包含如下說明:「如果你正在找尋保護信號,那麼當設置-用戶-ID命令執行時,將可能產生大量的這種信號」。4.3 + BSD產生名為core.prog的文件,其中prog是被執行的程序名的前1 6個字元。它對core文件給予了某種標識,所以是一種改進特徵。
表中「硬體故障」對應於實現定義的硬體故障。這些名字中有很多取自UNIX早先在DP-11上的實現。請查看你所使用的系統的手冊,以確切地確定這些信號對應於哪些錯誤類型。
下面比較詳細地說明這些信號。
• SIGABRT 調用abort函數時產生此信號。進程異常終止。
• SIGBUS 指示一個實現定義的硬體故障。
• SIGEMT 指示一個實現定義的硬體故障。
EMT這一名字來自PDP-11的emulator trap 指令。
• SIGFPE 此信號表示一個算術運算異常,例如除以0,浮點溢出等。
• SIGILL 此信號指示進程已執行一條非法硬體指令。
4.3BSD由abort函數產生此信號。SIGABRT現在被用於此。
• SIGIOT 這指示一個實現定義的硬體故障。
IOT這個名字來自於PDP-11對於輸入/輸出TRAP(input/output TRAP)指令的縮寫。系統V的早期版本,由abort函數產生此信號。SIGABRT現在被用於此。
• SIGQUIT 當用戶在終端上按退出鍵(一般採用Ctrl-\)時,產生此信號,並送至前台進
程組中的所有進程。此信號不僅終止前台進程組(如SIGINT所做的那樣),同時產生一個core文件。
• SIGSEGV 指示進程進行了一次無效的存儲訪問。
名字SEGV表示「段違例(segmentation violation)」。
• SIGSYS 指示一個無效的系統調用。由於某種未知原因,進程執行了一條系統調用指令,
但其指示系統調用類型的參數卻是無效的。
• SIGTRAP 指示一個實現定義的硬體故障。
此信號名來自於PDP-11的TRAP指令。
• SIGXCPU SVR4和4.3+BSD支持資源限制的概念。如果進程超過了其軟C P U時間限制,則產生此信號。
• SIGXFSZ 如果進程超過了其軟文件長度限制,則SVR4和4.3+BSD產生此信號。
摘自《UNIX環境高級編程》第10章 信號。

使用core文件調試程序
看下面的例子:
/*core_mp_test.c*/
#include
const char *str = "test";
void core_test(){
str[1] = 'T';
}

int main(){
core_test();
return 0;
}
編譯:
gcc –g core_mp_test.c -o core_mp_test
如果需要調試程序的話,使用gcc編譯時加上-g選項,這樣調試core文件的時候比較容易找到錯誤的地方。
執行:
./core_mp_test
段錯誤
運行core_mp_test程序出現了「段錯誤」,但沒有產生core文件。這是因為系統默認core文件的大小為0,所以沒有創建。可以用ulimit命令查看和修改core文件的大小。
ulimit -c 0
ulimit -c 1000
ulimit -c 1000
-c 指定修改core文件的大小,1000指定了core文件大小。也可以對core文件的大小不做限制,如:
ulimit -c unlimited
ulimit -c unlimited
如果想讓修改永久生效,則需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。
再次執行:
./core_mp_test
段錯誤 (core mped)
ls core.*
core.6133
可以看到已經創建了一個core.6133的文件.6133是core_mp_test程序運行的進程ID。
調式core文件
core文件是個二進制文件,需要用相應的工具來分析程序崩潰時的內存映像。
file core.6133
core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'core_mp_test'
在Linux下可以用GDB來調試core文件。
gdb core_mp_test core.6133
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show ing" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
Core was generated by `./core_mp_test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x080482fd in core_test () at core_mp_test.c:7
7 str[1] = 'T';
(gdb) where
#0 0x080482fd in core_test () at core_mp_test.c:7
#1 0x08048317 in main () at core_mp_test.c:12
#2 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6
GDB中鍵入where,就會看到程序崩潰時堆棧信息(當前函數之前的所有已調用函數的列表(包括當前函數),gdb只顯示最近幾個),我們很容易找到我們的程序在最後崩潰的時候調用了core_mp_test.c 第7行的代碼,導致程序崩潰。注意:在編譯程序的時候要加入選項-g。您也可以試試其他命令,如fram、list等。更詳細的用法,請查閱GDB文檔。
core文件創建在什麼位置
在進程當前工作目錄的下創建。通常與程序在相同的路徑下。但如果程序中調用了chdir函數,則有可能改變了當前工 作目錄。這時core文件創建在chdir指定的路徑下。有好多程序崩潰了,我們卻找不到core文件放在什麼位置。和chdir函數就有關系。當然程序 崩潰了不一定都產生core文件。
什麼時候不產生core文件
在下列條件下不產生core文件:
( a )進程是設置-用戶-ID,而且當前用戶並非程序文件的所有者;
( b )進程是設置-組-ID,而且當前用戶並非該程序文件的組所有者;
( c )用戶沒有寫當前工作目錄的許可權;
( d )文件太大。core文件的許可權(假定該文件在此之前並不存在)通常是用戶讀/寫,組讀和其他讀。
利用GDB調試core文件,當遇到程序崩潰時我們不再束手無策。

4. ulimit -c unlimited後為什麼還是不生成core文件,我寫了個段錯誤的程序

cat /proc/sys/kernel/core_pattern
看下core生成的路徑在哪

5. 如何生成core文件

1、先用#ulimit -a可以查看系統core文件的大小限制(第一行),core文件大小設置為0, 即沒有打開core mp設置;

[cpp] view plain print?

6. 段錯誤的段錯誤的常見形式

在編程中以下幾類做法容易導致段錯誤,基本上是錯誤地使用指針引起的。
1)訪問系統數據區,尤其是往系統保護的內存地址寫數據最常見就是給一個指針以0地址。
2)內存越界(數組越界,變數類型不一致等): 訪問到不屬於你的內存區域。
解決方法:我們在用C/C++語言寫程序的時候,物悉侍內存管理的絕大部分工作都是需要我們來做的。實際上,內存管理是一個比較繁瑣的工作,無論你多高明,經驗多豐富,難免會在此處犯些小錯誤,而通常這些錯誤又是那麼的淺顯而易於消除。但是手工「除蟲」(debug),往往是效率低下且讓人厭煩罩吵的,本文將就段錯誤這個內存訪問越界的錯誤談談如何快速定位這些段錯誤的語句。
下面將就以下的一個存在段錯誤的程序介紹幾種調試方法: 1 mmy_function (void)
2 {
3 unsigned char *ptr = 0x00;
4 *ptr = 0x00;
5 }
6
7 int main (void)
8 {
9 mmy_function ();
10
11 return 0;
12 } 作為一個熟練的C/C++程序員,以上代碼的bug應該是很清楚的,因為它嘗試操作地址為0的內存區域,而這個內存區域通常是不可訪問的禁區,當然就會出錯了。我們嘗試編譯運行它: xiaosuo@gentux test $ ./a.out
段錯誤 出錯並退出。 這種方法也是被大眾所熟知並廣泛採用的方法,首先我們需要一個帶有調試信息的可執行程序,所以我們加上「-g -rdynamic的參數進行編譯,然後用gdb調試運行這個新編譯的程序,具體步驟如下: xiaosuo@gentux test $ gcc -g -rdynamic d.c
xiaosuo@gentux test $ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type show ing to see the conditions.
There is absolutely no warranty for GDB. Type show warranty for details.
This GDB was configured as i686-pc-linux-gnu...Using host libthread_db library /lib/libthread
(gdb) r
Starting program: /home/xiaosuo/test/a.out
Program received signal SIGSEGV, Segmentation fault.
0x08048524 in mmy_function () at d.c:4
4 *ptr = 0x00;
(gdb) 不用一步步調試我們就找到了出錯位置d.c文件的第4行,其實就是如此的簡單。
從這里我們還發現進程是由於收到了SIGSEGV信號陸友而結束的。通過進一步的查閱文檔(man 7 signal),我們知道SIGSEGV默認handler的動作是列印」段錯誤的出錯信息,並產生Core文件,由此我們又產生了方法二。 The default action of certain signals is to cause a process to terminate and proce a core mp file, a disk file containing an image of the process's memory at the time of termination. A list of the signals which cause a process to mp core can be found in signal(7). 以 上資料摘自man page(man 5 core)。不過奇怪了,我的系統上並沒有找到core文件。後來,憶起為了漸少系統上的垃圾文件的數量,禁止了core文件的生成,查看了以下果真如此,將系統的core文件的大小限制在512K大小,再試: xiaosuo@gentux test $ ulimit -c
0
xiaosuo@gentux test $ ulimit -c 1000
xiaosuo@gentux test $ ulimit -c
1000
xiaosuo@gentux test $ ./a.out
段錯誤 (core mped)
xiaosuo@gentux test $ ls
a.out core d.c f.c g.c pango.c test_iconv.c test_regex.c core文件終於產生了,用gdb調試一下看看吧: xiaosuo@gentux test $ gdb ./a.out core
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type show ing to see the conditions.
There is absolutely no warranty for GDB. Type show warranty for details.
This GDB was configured as i686-pc-linux-gnu...Using host libthread_db library /lib/libthread.
warning: Can't read pathname for load map: 輸入/輸出錯誤。
Reading symbols from /lib/lib6...done.
Loaded symbols for /lib/li6
Reading symbols from /lib/ld-.2...done.
Loaded symbols for /lib/ld-linux.s2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048524 in mmy_function () at d.c:4
4 *ptr = 0x00;dfg #include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
/* A mmy function to make the backtrace more interesting. */
void
mmy_function (void)
{
unsigned char *ptr = 0x00;
*ptr = 0x00;
}
void mp(int signo)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
printf (Obtained %zd stack frames. , size);
for (i = 0; i < size; i++)
printf (%s , strings[i]);
free (strings);
exit(0);
}
int
main (void)
{
signal(SIGSEGV, &mp);
mmy_function ();
return 0;
}
運行結果:xiaosuo@gentux test $ gcc -g -rdynamic g.c
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(mp+0x19) [0x80486c2]
[0xffffe420]
./a.out(main+0x35) [0x804876f]

7. 如何正確獲得segfault等系統錯誤的log

系統有問題了。直接換個驗證過的系統盤重裝系統就行了,這樣就可以全程自動、順利解決 系統發生內部錯誤 的問題了。用u盤或者硬碟這些都是可以的,且安裝速度非常快。但關鍵是:要有兼容性好的(兼容ide、achi、Raid模式的安裝)

8. coremp導出堆內存

系統中,應用程序崩潰,一般會產生core文件,如何根據core文件查找問題的所在,並做相應的分析和調試,是非常重要的。

什麼是Core Dump?
Core的意思是內存, Dump的意思是扔出來, 堆出來.開發和使用Unix程序時, 有時程鄭睜旅序莫名其妙的down了, 卻沒有任何的提示(有時候會提示core mped). 這時候可以查看一下有沒有形如core.進程號的文件生成, 這個文件便是操作系統把程序down掉時的內存內容扔出來生成的, 它可以做為調試程序的參考.
core mp又叫核心轉儲, 當程序運行過程中發生異常, 程序異常退出時, 由操作系統把程序當前的內存狀況存儲在一個core文件中, 叫core mp.

COREDUMP是由系統全局設置和程序設置後才能生成的,當發生異常時,由內核將程序映像轉儲,和GCC和GDB沒有直接關系,GCC中加-g參數是為了獲得符號表,便於GDB分析,一般只包含一個線程的TRACE,COREDUMP所反饋的信息也不是完全准確的,它只是程序宕機前的一個映像(主要是調用堆棧及全局量),如果程序跑飛了那參考價值就不大了。

為什麼沒有core文件生成呢?
有時候程序down了, 但是core文件卻沒有生成. core文件的生成跟你當前系統的環境設置有關系, 可以用下面的語句設置一下, 然後再運行程序便成生成core文件.
ulimit -c unlimited(將coremp文件設置位無限制)

可用ulimit -a命令查看系統限制,如果此時的core file size (blocks, -c) 0則不會產生core文件。
core文件生成的位置一般於運行程序的路徑相同, 文件名一般為core.進程號

當獲得了core文件以後,就可以利用命令gdb進行查找,參數一是應用程序的名稱,參數二是core文件
如: gdb [...]xmsd [...]/xmsd_PID1065_SIG11.core

然後輸入bt或者where找到錯誤發生的位置和相應的堆棧信息。就可知道發生錯誤時的函數調用關系,然後可以使用up或者down查看上一喊凳條和下一條具體詳細信息。這樣便能對問題進行大概定早碰位,然後看源代碼,進行分析。

常式:

$vi foo.c

編輯如下:
#include <stdio.h>

static void sub(void);

int main(void)

{

sub();

return 0;

}

static void sub(void)

{

int *p = NULL;

/* derefernce a null pointer, expect core mp. */

printf("%d", *p);

}

$more foo.c //查看代碼

$gcc -Wall -g foo.c

$./a.out

段錯誤

當core file size (blocks, -c) 0時,不會有core文件生成,但是我們已經設置位unlimited,所以在ls查看的時候:

a.out core foo.c
然後使用GDB進行解析

$gdb --core=core

GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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 ing"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
[New Thread 14364]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x0000000000400548 in ?? ()
(gdb)bt

#0 0x0000000000400548 in ?? ()
#1 0x0000000000000000 in ?? ()
(gdb)file ./a.out
Reading symbols from /local/test_gdb/a.out...done.

(gdb) bt
#0 0x0000000000400548 in sub () at foo.c:13
#1 0x000000000040052d in main () at foo.c:6
(gdb) l
1 #include<stdio.h>
2 static void sub(void);
3
4 int main(void)
5 {
6 sub();
7 return 0;
8 }
9
10 static void sub(void)
(gdb) l
11 {
12 int *p = NULL;
13 printf("%d",*p);
14 }
通過上面就可以看到問題出在什麼地方。
點擊閱讀全文

9. linux 出現 segment fault怎麼解決

1. 段錯誤是什麼
一句話來說,段錯誤是指訪問的內存超出了系統給這個程序所設定的內存空間,例如訪問了不存在的內存地址、訪問了系統保護的內存地址、訪問了只讀的內存地址等等情況。這里貼一個對於「段錯誤」的准確定義(參考Answers.com):

A segmentation fault (often shortened to segfault) is a particular error condition that can occur ring the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.

Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.

On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.

2. 段錯誤產生的原因
2.1 訪問不存在的內存地址

#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = NULL;
*ptr = 0;
}

2.2 訪問系統保護的內存地址

#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = (int *)0;
*ptr = 100;
}

2.3 訪問只讀的內存地址

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char *ptr = "test";
strcpy(ptr, "TEST");
}

2.4 棧溢出

#include<stdio.h>
#include<stdlib.h>
void main()
{
main();
}

等等其他原因。
3. 段錯誤信息的獲取
程序發生段錯誤時,提示信息很少,下面有幾種查看段錯誤的發生信息的途徑。
3.1 dmesg
dmesg可以在應用程序crash掉時,顯示內核中保存的相關信息。如下所示,通過dmesg命令可以查看發生段錯誤的程序名稱、引起段錯誤發生的內存地址、指令指針地址、堆棧指針地址、錯誤代碼、錯誤原因等。以程序2.3為例:
panfeng@ubuntu:~/segfault$ dmesg
[ 2329.479037] segfault3[2700]: segfault at 80484e0 ip 00d2906a sp bfbbec3c error 7 in libc-2.10.1.so[cb4000+13e000]

3.2 -g
使用gcc編譯程序的源碼時,加上-g參數,這樣可以使得生成的二進制文件中加入可以用於gdb調試的有用信息。以程序2.3為例:
panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c

3.3 nm
使用nm命令列出二進制文件中的符號表,包括符號地址、符號類型、符號名等,這樣可以幫助定位在哪裡發生了段錯誤。以程序2.3為例:

panfeng@ubuntu:~/segfault$ nm segfault3
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
080484ec r __FRAME_END__
08049f1c d __JCR_END__
08049f1c d __JCR_LIST__
0804a014 A __bss_start
0804a00c D __data_start
08048490 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
w __gmon_start__
0804848a T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048420 T __libc_csu_fini
08048430 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a014 A _edata
0804a01c A _end
080484bc T _fini
080484d8 R _fp_hw
080482bc T _init
08048330 T _start
0804a014 b completed.6990
0804a00c W data_start
0804a018 b dtor_idx.6992
080483c0 t frame_mmy
080483e4 T main
U memcpy@@GLIBC_2.0

3.4 ldd
使用ldd命令查看二進製程序的共享鏈接庫依賴,包括庫的名稱、起始地址,這樣可以確定段錯誤到底是發生在了自己的程序中還是依賴的共享庫中。以程序2.3為例:
panfeng@ubuntu:~/segfault$ ldd ./segfault3
linux-gate.so.1 => (0x00e08000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00675000)
/lib/ld-linux.so.2 (0x00482000)

4. 段錯誤的調試方法
4.1 使用printf輸出信息
這個是看似最簡單但往往很多情況下十分有效的調試方式,也許可以說是程序員用的最多的調試方式。簡單來說,就是在程序的重要代碼附近加上像printf這類輸出信息,這樣可以跟蹤並列印出段錯誤在代碼中可能出現的位置。
為了方便使用這種方法,可以使用條件編譯指令#ifdef DEBUG和#endif把printf函數包起來。這樣在程序編譯時,如果加上-DDEBUG參數就能查看調試信息;否則不加該參數就不會顯示調試信息。
4.2 使用gcc和gdb
4.2.1 調試步驟
1、為了能夠使用gdb調試程序,在編譯階段加上-g參數,以程序2.3為例:
panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c

2、使用gdb命令調試程序:

panfeng@ubuntu:~/segfault$ gdb ./segfault3
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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 ing"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/panfeng/segfault/segfault3...done.
(gdb)

3、進入gdb後,運行程序:

(gdb) run
Starting program: /home/panfeng/segfault/segfault3

Program received signal SIGSEGV, Segmentation fault.
0x001a306a in memcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb)

從輸出看出,程序2.3收到SIGSEGV信號,觸發段錯誤,並提示地址0x001a306a、調用memcpy報的錯,位於/lib/tls/i686/cmov/libc.so.6庫中。
4、完成調試後,輸入quit命令退出gdb:

(gdb) quit
A debugging session is active.

Inferior 1 [process 3207] will be killed.

Quit anyway? (y or n) y

4.2.2 適用場景
1、僅當能確定程序一定會發生段錯誤的情況下使用。
2、當程序的源碼可以獲得的情況下,使用-g參數編譯程序。
3、一般用於測試階段,生產環境下gdb會有副作用:使程序運行減慢,運行不夠穩定,等等。
4、即使在測試階段,如果程序過於復雜,gdb也不能處理。
4.3 使用core文件和gdb
在4.2節中提到段錯誤會觸發SIGSEGV信號,通過man 7 signal,可以看到SIGSEGV默認的handler會列印段錯誤出錯信息,並產生core文件,由此我們可以藉助於程序異常退出時生成的core文件中的調試信息,使用gdb工具來調試程序中的段錯誤。
4.3.1 調試步驟
1、在一些Linux版本下,默認是不產生core文件的,首先可以查看一下系統core文件的大小限制:
panfeng@ubuntu:~/segfault$ ulimit -c
0

2、可以看到默認設置情況下,本機Linux環境下發生段錯誤時不會自動生成core文件,下面設置下core文件的大小限制(單位為KB):
panfeng@ubuntu:~/segfault$ ulimit -c 1024
panfeng@ubuntu:~/segfault$ ulimit -c
1024

3、運行程序2.3,發生段錯誤生成core文件:
panfeng@ubuntu:~/segfault$ ./segfault3
段錯誤 (core mped)

4、載入core文件,使用gdb工具進行調試:

panfeng@ubuntu:~/segfault$ gdb ./segfault3 ./core
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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 ing"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/panfeng/segfault/segfault3...done.

warning: Can't read pathname for load map: 輸入/輸出錯誤.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./segfault3'.
Program terminated with signal 11, Segmentation fault.
#0 0x0018506a in memcpy () from /lib/tls/i686/cmov/libc.6

從輸出看出,同4.2.1中一樣的段錯誤信息。
5、完成調試後,輸入quit命令退出gdb:
(gdb) quit

4.3.2 適用場景
1、適合於在實際生成環境下調試程序的段錯誤(即在不用重新發生段錯誤的情況下重現段錯誤)。
2、當程序很復雜,core文件相當大時,該方法不可用。
4.4 使用objmp
4.4.1 調試步驟
1、使用dmesg命令,找到最近發生的段錯誤輸出信息:
panfeng@ubuntu:~/segfault$ dmesg
... ...
[17257.502808] segfault3[3320]: segfault at 80484e0 ip 0018506a sp bfc1cd6c error 7 in libc-2.10.1.so[110000+13e000]

其中,對我們接下來的調試過程有用的是發生段錯誤的地址:80484e0和指令指針地址:0018506a。
2、使用objmp生成二進制的相關信息,重定向到文件中:
panfeng@ubuntu:~/segfault$ objmp -d ./segfault3 > segfault3Dump

其中,生成的segfault3Dump文件中包含了二進制文件的segfault3的匯編代碼。
3、在segfault3Dump文件中查找發生段錯誤的地址:

panfeng@ubuntu:~/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

通過對以上匯編代碼分析,得知段錯誤發生main函數,對應的匯編指令是movl $0x80484e0,0x1c(%esp),接下來打開程序的源碼,找到匯編指令對應的源碼,也就定位到段錯誤了。
4.4.2 適用場景
1、不需要-g參數編譯,不需要藉助於core文件,但需要有一定的匯編語言基礎。
2、如果使用了gcc編譯優化參數(-O1,-O2,-O3)的話,生成的匯編指令將會被優化,使得調試過程有些難度。
4.5 使用catchsegv
catchsegv命令專門用來撲獲段錯誤,它通過動態載入器(ld-linux.so)的預載入機制(PRELOAD)把一個事先寫好的庫(/lib/libSegFault.so)載入上,用於捕捉斷錯誤的出錯信息。

panfeng@ubuntu:~/segfault$ catchsegv ./segfault3
Segmentation fault (core mped)
*** Segmentation fault
Register mp:

EAX: 00000000 EBX: 00fb3ff4 ECX: 00000002 EDX: 00000000
ESI: 080484e5 EDI: 080484e0 EBP: bfb7ad38 ESP: bfb7ad0c

EIP: 00ee806a EFLAGS: 00010203

CS: 0073 DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b

Trap: 0000000e Error: 00000007 OldMask: 00000000
ESP/signal: bfb7ad0c CR2: 080484e0

Backtrace:
/lib/libSegFault.so[0x3b606f]
??:0(??)[0xc76400]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xe89b56]
/build/buildd/eglibc-2.10.1/csu/../sysdeps/i386/elf/start.S:122(_start)[0x8048351]

Memory map:

10. GDB 調試Coremp問題

如果用CMake編譯工程,則使用選項CMAKE_BUILD_TYPE=Debug:

這樣做g++編譯時就會包含選項-g。如果要同時包含-ggdb選項,可以設置變數CMAKE_CXX_FLAGS_DEBUG。

%e - insert coremping executable name into filename 添加導致產生core的命令名
%p - insert pid into filename 添加pid(進程id)

運行程序,生成core文件。下面的命令強燃冊制生成core文件:

或者進入gdb後

file從文件exec載入symbol和executable, core從core中載入coremp

如果是調試Core的機器(host)不是生成Core的機器(target),則動態庫可能不在程序指定的位置上。這時需要指定動態庫的位置。

首先用info sharedlibrary,可以查看動態庫的symbol是否載入正確

如果庫在host上的布局與在target上的布局相同,則使用solib-absolute-prefix比較方便。

target上:

host上:

則可以設置solib-search-path為:

solib-absolute-prefix有個更常用的別名sysroot,所以如下的命令是一樣的:

設置solib-search-path可以指定多個路徑,路徑之間用:隔開。

在多線程的環境下,可以用info threads顯示擾段配所有線程,thread指定緩指線程為當前線程。

GDB 常用法
GDB 調試Coremp問題
嵌入式開發中GDB調試Coremp問題
嵌入式開發中GDB串口遠程調試
用backtrace()調試coremp問題
Valgrind memcheck 用法
Address Sanitizer 用法

段錯誤及GDB Coremp調試方法
https://blog.csdn.net/oscarjulia/article/details/74256997

gdb調試多進程與多線程
https://blog.csdn.net/snow_5288/article/details/72982594

閱讀全文

與段錯誤沒生成core文件相關的資料

熱點內容
產品在網站優化多少錢 瀏覽:992
亂碼文件夾 瀏覽:480
mc編程後怎麼模擬加工 瀏覽:153
如何恢復刷機後的數據 瀏覽:243
重裝系統win81教程 瀏覽:317
nero10安裝教程 瀏覽:182
handJoy游戲大廳安卓版 瀏覽:663
wow的配置文件怎麼重置 瀏覽:921
css代碼在線編輯 瀏覽:383
哪個狼人殺app可以觀戰 瀏覽:797
你懂的免費qq空間 瀏覽:858
電影曲面是在哪裡拍的app 瀏覽:137
ipadwps怎麼改文件名 瀏覽:162
怎麼將結果顯示在jsp 瀏覽:819
word文檔解析度 瀏覽:108
如何在網站主頁中插入圖像 瀏覽:258
特斯拉數據需要多少伺服器 瀏覽:828
手機百度雲無法看種子文件 瀏覽:690
都有哪些街拍網站 瀏覽:482
賣家鄉特產要什麼網站賣呢 瀏覽:102

友情鏈接