使用gdb和core文件定位问题

文章目录

    • 1. 出问题的源码
    • 2. 寻找core文件
    • 3. 编译时配置-g选项
    • 4. 问题定位
    • 5. 问题说明

作为一个使用printf来定位问题的嵌入式菜鸟,第一次使用gdb定位了一个问题,这里记录一下。

1. 出问题的源码

今天写代码时遇到了一个segmentation fault的问题。源代码如下,每秒读取一个文件,但是运行一段时间后出现了segmentation fault报错。担心问题不好复现,就尝试使用gdb来定位一下问题。

#include 
#include 
#include void read_version()
{FILE *fp;char line[10240];fp = fopen("/proc/version", "r");while(fgets(line, sizeof(line), fp) != NULL) {printf("%s\n", line);}
}int main(int argc, char *argv[])
{while (1) {read_version();sleep(1);}return 0;
}

报错信息如上

Linux version 5.10.0-60.18.0.13.oe2203.raspi.aarch64 (abuild@obs-worker1640081563-aarch64-0001) (gcc_old (GCC) 10.3.1, GNU ld (GNU Binutils) 2.37) #1 SMP PREEMPT Wed Mar 30 05:01:23 UTC 2022Segmentation fault (core dumped)

2. 寻找core文件

错误信息显示出现了core文件,查找资料说一般core文件会在程序执行的目录上保留,但是我在当前目录下并没有找到core文件。网上查找资料后问题解决,需要指定一下core文件的路径

proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。
可通过以下命令修改此文件:
echo “/corefile/core-%e-%p-%t” > core_pattern,可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
以下是参数列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
  1. core文件所在的文件夹要有写入权限,在home目录下创建一个corefile文件夹用于存放core文件

  2. 用root权限执行下面的命令,配置core文件存放路径

    echo /home/jimmy/corefile/core-%e-%p-%t” > /proc/sys/kernel/core_pattern
    

    可以使用命令确定路径配置正确

    cat /proc/sys/kernel/core_pattern
    

3. 编译时配置-g选项

为了便于定位问题,编译时需要配置-g选项,将debug信息编译进可执行文件中,我的Makefile如下

all:gcc -o read_file -g read_file.c

4. 问题定位

运行代码复现问题,在corefile目录下就可以看到core文件了

[jimmy@openEuler corefile]$ ls
core-read_file-1418-1666968069”
[jimmy@openEuler corefile]$
[jimmy@openEuler gdb]$ gdb read_file /home/jimmy/corefile/core-read_file-1418-1666968069”
GNU gdb (GDB) openEuler 11.1-1.oe2203
Copyright (C) 2021 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 copying" and "show warranty" for details.
This GDB was configured as "aarch64-openEuler-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from read_file...
[New LWP 1418]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".
Core was generated by `./read_file'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000007f9af16cbc in fgets () from /usr/lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.34-70.oe2203.aarch64
(gdb) bt
#0  0x0000007f9af16cbc in fgets () from /usr/lib64/libc.so.6
#1  0x0000000000400748 in read_version () at read_file.c:11
#2  0x000000000040077c in main (argc=1, argv=0x7fe26657c8) at read_file.c:19
(gdb) f 1
#1  0x0000000000400748 in read_version () at read_file.c:11
11              while(fgets(line, sizeof(line), fp) != NULL) {
(gdb) info args
No arguments.
(gdb) p line
$1 = "Linux version 5.10.0-60.18.0.13.oe2203.raspi.aarch64 (abuild@obs-worker1640081563-aarch64-0001) (gcc_old (GCC) 10.3.1, GNU ld (GNU Binutils) 2.37) #1 SMP PREEMPT Wed Mar 30 05:01:23 UTC 2022\n", '\000' <repeats 5698 times>...
(gdb) p fp
$2 = (FILE *) 0x0
(gdb) quit
[jimmy@openEuler gdb]$

基本操作说明:

  • gdb [executable_file] [core_file]: gdb+core文件的基本使用方式
  • 运行后就可以看到代码是挂在fgets函数处
  • 使用bt命令可以看到函数的调用栈 main => read_version => fgets
  • 使用命令 “f 1"可以看到具体的栈帧,1代表frame1,也就是read_version函数
  • p是print的缩写,可以打印出函数中的变量
  • 打印出的line基本正常,fp为0,说明是open函数失败,导致fp为0,fgets函数执行失败

至此问题定位完毕

5. 问题说明

网上搜了一下,这个问题出现的原因是只有open函数,而没有close函数。文件打开1000次后,就会导致句柄不够用,从而导致open函数失败。

在代码中添加次数统计打印,看一下多少次后会出现core dump的问题

nt main(int argc, char *argv[])
{int count = 0;while (1) {read_version();printf("count = %d\n", count);count++;}return 0;
}

错误打印如下

count = 1019
Linux version 5.10.0-60.18.0.13.oe2203.raspi.aarch64 (abuild@obs-worker1640081563-aarch64-0001) (gcc_old (GCC) 10.3.1, GNU ld (GNU Binutils) 2.37) #1 SMP PREEMPT Wed Mar 30 05:01:23 UTC 2022count = 1020
Segmentation fault (core dumped)

可以看到是1020次出现core dump问题,与网上的说明基本一致,问题得解


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部