core dump又叫核心轉儲, 當程序運行過程中發(fā)生異常, 程序異常退出時, 由操作系統(tǒng)把程序當前的內(nèi)存狀況存儲在一個core文件中, 叫core dump. (linux中如果內(nèi)存越界會收到SIGSEGV信號,然后就會core dump)
在程序運行的過程中,有的時候我們會遇到Segment fault(段錯誤)這樣的錯誤。這種看起來比較困難,因為沒有任何的棧、trace信息輸出。該種類型的錯誤往往與指針操作相關。往往可以通過這樣的方式進行定位。
一 造成segment fault,產(chǎn)生core dump的可能原因
1.內(nèi)存訪問越界
a) 由于使用錯誤的下標,導致數(shù)組訪問越界
b) 搜索字符串時,依靠字符串結束符來判斷字符串是否結束,但是字符串沒有正常的使用結束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函數(shù),將目標字符串讀/寫爆。應該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數(shù)防止讀寫越界。
2 多線程程序使用了線程不安全的函數(shù)。
3 多線程讀寫的數(shù)據(jù)未加鎖保護。對于會被多個線程同時訪問的全局數(shù)據(jù),應該注意加鎖保護,否則很容易造成core dump
4 非法指針
a) 使用空指針
b) 隨意使用指針轉換。一個指向一段內(nèi)存的指針,除非確定這段內(nèi)存原先就分配為某種結構或類型,或者這種結構或類型的數(shù)組,否則不要將它轉換為這種結構或類型的指針,而應該將這段內(nèi)存拷貝到一個這種結構或類型中,再訪問這個結構或類型。這是因為如果這段內(nèi)存的開始地址不是按照這種結構或類型對齊的,那么訪問它時就很容易因為bus error而core dump.
5 堆棧溢出.不要使用大的局部變量(因為局部變量都分配在棧上),這樣容易造成堆棧溢出,破壞系統(tǒng)的棧和堆結構,導致出現(xiàn)莫名其妙的錯誤。
二 配置操作系統(tǒng)使其產(chǎn)生core文件
首先通過ulimit命令查看一下系統(tǒng)是否配置支持了dump core的功能。通過ulimit -c或ulimit -a,可以查看core file大小的配置情況,如果為0,則表示系統(tǒng)關閉了dump core??梢酝ㄟ^ulimit -c unlimited來打開。若發(fā)生了段錯誤,但沒有core dump,是由于系統(tǒng)禁止core文件的生成。
解決方法:
$ulimit -c unlimited ?。ㄖ粚Ξ斍皊hell進程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一勞永逸)
# ulimit -c
0
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
三 用gdb查看core文件
發(fā)生core dump之后, 用gdb進行查看core文件的內(nèi)容, 以定位文件中引發(fā)core dump的行.
gdb [exec file] [core file]
如: gdb ./test test.core
四 樣例
1. 空指針
樣例:
#include <stdio.h>
int main(void)
{
printf("hello world! dump core for set value to NULL pointer/n");
*(char *)0 = 0;
return 0;
}
# gcc -g test.c -o test
# ./test
hello world! dump core for set value to NULL pointer
Segmentation fault
/× Get segmentation fault, but there is no core dump. The reason is that the system configure core file size to zero ×/
# ls
test test.c
/* Set core file size to unlimited */
# ulimit -c unlimited
# ./test
hello world! dump core for set value to NULL pointer
Segmentation fault (core dumped)
/* Get core dump after change core file size. */
# ls
core.5581 test test.c
/* gdb to debug core dump */
# gdb test core.5581
GNU gdb Red Hat Linux (6.3.0.0-1.132.EL4rh)
Copyright 2004 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 copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib64/tls/libc.so.6...done.
Loaded symbols for /lib64/tls/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
#0 0x000000000040048b in main () at test.c:6
warning: Source file is more recent than executable.
6 *(char *)0 = 0;
(gdb) bt
#0 0x000000000040048b in main () at test.c:6
2. 棧溢出。
有關棧溢出的程序,請參見:一個測試棧大小的小程序
http://blog.163.com/huang_bp/blog/static/12311983720099150746901/edit/
# gcc -g test.c -o test -lpthread
# ls
test test.c
# ./test
...
Segmentation fault (core dumped)
# ls
core.5616 test test.c
# gdb test core.5616
GNU gdb Red Hat Linux (6.3.0.0-1.132.EL4rh)
Copyright 2004 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 copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib64/tls/libpthread.so.0...done.
Loaded symbols for /lib64/tls/libpthread.so.0
Reading symbols from /lib64/tls/libc.so.6...done.
Loaded symbols for /lib64/tls/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
#0 0x0000002a957c051e in vfprintf () from /lib64/tls/libc.so.6
(gdb) list
13
14 buffer[0]=i;
15 test(s);
16 }
17
18 int main()
19 {
20 pthread_t p;
21
22 pthread_create(&p, NULL, &test, NULL);
對于棧溢出的segment fault沒有第一個定位方便,需要分析代碼才能判斷出原因。
聯(lián)系客服