Linux下core文件产生的一些注意问题

前面转载了一篇文章关于core文件的产生和调试使用的设置,但在使用有一些需要注意的问题,如 在什么情况 才会正确地产生core文件。

列出一些常见问题:

一,如何使用core文件

1. 使用core文件

在core文件所在目录下键入:

gdb -c core

它会启动GNU的调试器,来调试core文件,并且会显示生成此core文件的程序名,中止此程序的信号等等。

如果你已经知道是由什么程序生成此core文件的,比如MyServer崩溃了生成core.12345,那么用此指令调试:

gdb -c core MyServer

以下怎么办就该去学习gdb的使用了

2. 一个小方法来测试产生core文件

直接输入指令:kill -s SIGSEGV $$

二,程序产生core的原因

造成程序coredump的原因很多,这里根据以往的经验总结一下:

1 内存访问越界
a) 由于使用错误的下标,导致数组访问越界
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

2 多线程程序使用了线程不安全的函数。
应该使用下面这些可重入的函数,尤其注意红色标示出来的函数,它们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

3 多线程读写的数据未加锁保护。
对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump

4 非法指针
a) 使用空指针
b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump.

5 堆栈溢出
不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。

三,注意的问题

在Linux下要保证程序崩溃时生成Coredump要注意这些问题:

一、要保证存放Coredump的目录存在且进程对该目录有写权限。存放Coredump的目录即进程的当前目录,一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动,则脚本可能会修改当前目录,这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看”/proc/<进程pid>/cwd“符号链接的目标来确定进程真正的当前目录地址。通过系统服务启动的进程也可通过这一方法查看。

二、若程序调用了seteuid()/setegid()改变了进程的有效用户或组,则在默认情况下系统不会为这些进程生成Coredump。很多服务程序都会调用seteuid(),如MySQL,不论你用什么用户运行mysqld_safe启动MySQL,mysqld进行的有效用户始终是msyql用户。如果你当初是以用户A运行了某个程序,但在ps里看到的这个程序的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成core dump,需要将/proc/sys/fs /suid_dumpable文件的内容改为1(一般默认是0)。

三、要设置足够大的Core文件大小限制了。程序崩溃时生成的Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少,要保证生成Core文件还是将大小限制设为unlimited为好。

在shell里使用命令:ulimit -c unlimited,这样进行修改只是对本次会话有效,是临时的,如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf

如下:

[[email protected] ~]# vim  /etc/profile

结果如图:

把红框里的行注释,并新加入一行:

ulimit -c unlimited

保存,退出即可。

四,产生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_dump_test.c*/
#include <stdio.h>
const char *str = "test";
void core_test(){
str[1] = ‘T‘;
}

int main(){
core_test();
return 0;
}

编译:
gcc –g core_dump_test.c -o core_dump_test

如果需要调试程序的话,使用gcc编译时加上-g选项,这样调试core文件的时候比较容易找到错误的地方。

执行:
./core_dump_test
段错误

运行core_dump_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_dump_test
段错误 (core dumped)
ls core.*
core.6133

可以看到已经创建了一个core.6133的文件.6133是core_dump_test程序运行的进程ID。

调式core文件
core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像。

file core.6133

core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from ‘core_dump_test‘

在Linux下可以用GDB来调试core文件。

gdb core_dump_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 copying" 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_dump_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_dump_test.c:7
7           str[1] = ‘T‘;
(gdb) where
#0  0x080482fd in core_test () at core_dump_test.c:7
#1  0x08048317 in main () at core_dump_test.c:12
#2  0x42015574 in __libc_start_main () from /lib/tls/libc.so.6

GDB中键入where,就会看到程序崩溃时堆栈信息(当前函数之前的所有已调用函数的列表(包括当前函数),gdb只显示最近几个),我们很容易找到我们的程序在最后崩溃的时候调用了core_dump_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文件,当遇到程序崩溃时我们不再束手无策。

文章出处:http://blog.csdn.net/fengxinze/article/details/6800175

时间: 2024-11-05 12:25:25

Linux下core文件产生的一些注意问题的相关文章

linux下core文件的调试(valgrind使用)

1.linux下可以使用valgrind来检测内存泄露和相关问题.例如恒生中间件启动,可以加上以下 valgrind --error-limit=no --tool=memcheck --leak-check=full --log-file=ufx.log hsserver -start mainsvr -f ar_ufx.xml -s 0 -t ar -c 2.core文件的调试 gdb hsserver.exe core.24679进入后. 输入bt或者where命令. f命令:进入栈 p命

linux下core文件调试方法(转载)

转自于:http://blog.csdn.net/fcryuuhou/article/details/8507775 在程序遇到段错误不寻常退出时,一般是访问内存出错.但是不会给出程序哪里出现的问题,这个时候就需要core文件来帮助调试. 内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息).使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数. 1.core文件的生成开关和大小限制 1)使用ulimit -c命令可查看core文件的生成开关.若结果

linux下core文件设置(转)

在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息).使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数. 1.core文件的生成开关和大小限制 1)使用ulimit -c命令可查看core文件的生成开关.若结果为0,则表示关闭了此功能,不会生成core文件. 2)使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte).若ulimit -c unlimited,则表示cor

linux 下core文件生成、路径、格式设置及调试

core文件生成及调试1 代码 #include<stdio.h> int main() { int *p = NULL; *p = 0; return 0; } 2 在当前shell执行ulimit -c unlimited 注意:该命令只在当前shell生效,其他shell会失效ulimit -c是0,生成core文件失败. 3 设置core文件格式和生成路径,默认在执行程序当前目录下,执行以下两条命令: echo "1" > /proc/sys/kernel/c

Linux下core文件调试

1,ulimit -a查看默认参数 2,ulimit -c 1024 设置core文件大小,如果超过1024个blocks,则不会产生core文件 注:tune2fs -l /dev/sda8 输出分区信息,包括block大小,此处为4096 程序: 编译:g++ -g test.cpp 3, gdb  --core=core(core文件名) gdb -c core 4,bt 发现没有任何堆栈信息,调用file 通告 5,再次调用bt 输出堆栈信息 可知,错误发生在程序fun()函数中的第8行

Linux下查看文件和文件夹大小 删除日志

场景:在sts中执行自动部署时候maven提示No space left on device错误,后来经检查发现是磁盘空间满了,用下面的方法分析发现tomcat下面的logs目录占用了很大的空间,删除多余的日志问题解决! 1 Linux下查看文件和文件夹大小 当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力.  du可以查看文件及文件夹的大小. 两者配合使用,非常有效.比如用df查看哪个一

linux下修改文件的用户组chgrp和文件所有者chown

1. linux下修改文件用户组 chgrp: change group的简写,修改文件所属的用户组. chgrp users test.log 修改后查看 ls -l -rwxrwx--- 1 work users 0 Jun 8 15:46 test.log 如果要修改该目录下所有文件和目录,使用-R参数. chgrp -R users test 要被改变的group名,必须在 /etc/group 文件中. /etc/group文件记录系统中所有的组名称. 2. linux下修改文件所有者

修改Linux下的文件以及文件夹的权限

如何在Linux中管理文件和文件夹的权限? 2014-02-12 10:58 布加迪编译 51CTO 字号:T | T Linux系统有严格的权限管理制度,操作者权限与文件权限不匹配时将无法对文件进行任何操作.对许多Linux用户来说,习惯于文件的权限和所有权可能有点难度.本文从命令行开始入手,教您在Linux中管理文件和文件夹权限的方法. AD:51CTO学院:IT精品课程在线看! [51CTO精选译文]对许多Linux用户来说,习惯于文件的权限和所有权可能有点难度.人们通常认为,想进入到这种

如何在windows下和linux下获取文件(如exe文件)的详细信息和属性

程序员都很懒,你懂的! 最近在项目开发中,由cs开发的exe的程序,需要自动升级,该exe程序放在linux下,自动升级时检测不到该exe程序的版本号信息,但是我们客户端的exe程序需要获取服务器上新程序的版本号信息.最后由我用java实现linux上exe文件的版本号读取功能.下面是详细代码: package com.herman.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.I