IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> GDB分析core dump -> 正文阅读

[系统运维]GDB分析core dump

Core dump

core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIGSEGV信号,然后就会core dump)

在程序运行的过程中,有的时候我们会遇到Segment fault(段错误)这样的错误。这种看起来比较困难,因为没有任何的栈、trace信息输出。该种类型的错误往往与指针操作相关。往往可以通过这样的方式进行定位。

配置操作系统产生core文件

ulimit -c 或者 ulimit -a查看core file文件大小的配置情况

比如我在自己的Ubuntu系统随便打开一个终端

pc@mypc:~$ ulimit -a
core file size          					(blocks, -c) 0
data seg size          				 (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               						(blocks, -f) unlimited
pending signals                 	(-i) 62923
max locked memory       	(kbytes, -l) 65536
max memory size         		(kbytes, -m) unlimited
open files                    		  	(-n) 1024
pipe size            						(512 bytes, -p) 8
POSIX message queues    (bytes, -q) 819200
real-time priority              	(-r) 0
stack size              					(kbytes, -s) 8192
cpu time               					(seconds, -t) unlimited
max user processes            (-u) 62923
virtual memory          			(kbytes, -v) unlimited
file locks                      			(-x) unlimited

此时“core file size ”大小为0,说明终端没有打开core dump,解决方法:

ulimit -c unlimited(只对当前终端进程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一劳永逸)

使用gdb查看core文件

在发生了core dump之后,如何使用gdb查看core文件内容,以定位文件中引发core dump的行呢?
我们通过以下“test_gdb.cpp”代码说明,该代码中有一个很明显的数组越界错误

#include <iostream>

void fun(){
    char v[10];
    for(int i = 0; i <= 10; i++){
        v[i] = i;
    }
}

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

编译并运行程序

pc@mypc:~$ g++ -g main.cpp -o a.out
pc@mypc:~$ ./a.out 
段错误 (核心已转储)

意料之中,运行该代码的时候发生了段错误,系统捕捉这一错误并在终端所在文件夹里生成了core文件。接下来在同一个终端里输入:

  • gdb [exec file] [core file] 命令行格式打开gdb和生成的core文件
# gdb [exec file] [core file]
pc@mypc:~$ gdb ./a.out core
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 ./test_gdb...done.
[New LWP 31499]
Core was generated by `./test_gdb'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51	../sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.

gdb的提示信息告诉我们错误发生在"…/sysdeps/unix/sysv/linux/raise.c:51"位置上,错误原因是"…/sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.",这是由于数组越界发生的系统内部错误,我们不用管它。直接回溯(backtrace)错误发生的位置:

  • bt 回溯错误函数的调用关系
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f7ad2fa1921 in __GI_abort () at abort.c:79
#2  0x00007f7ad2fea967 in __libc_message (action=action@entry=do_abort, 
    fmt=fmt@entry=0x7f7ad31178fb "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f7ad3095b61 in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=false, 
    msg=msg@entry=0x7f7ad31178d9 "stack smashing detected") at fortify_fail.c:33
#4  0x00007f7ad3095b22 in __stack_chk_fail () at stack_chk_fail.c:29
#5  0x0000559718536977 in fun () at /home/gao/Cpp_Projects/test_gdb/main.cpp:8
#6  0x0000559718536994 in main () at /home/gao/Cpp_Projects/test_gdb/main.cpp:14

gdb提示中每一条消息前边都有一个编号,其中很多都是系统内部函数的调用错误,但是我们只关心自己代码里边的问题。于是我们可以输入以下命令进行更进一步的调试:

  • frame [number] 单独查看某函数中的错误。
  • list 查看错误位置附近的代码
  • info locals 查看错误函数中的局部变量
  • print [var_name]p [var_name] 查看单独某一个变量的值
(gdb) frame 5
 #5  0x0000559718536977 in fun () at /home/gao/Cpp_Projects/test_gdb/main.cpp:8
8	}
(gdb) list
	3	void fun(){
	4	    char v[10];
	5	    for(int i = 0; i <= 10; i++){
	6	        v[i] = i;
	7	    }
	8	}
	9	
	10	int main() {
	11	    int a,b;
	12	    a = 0;
(gdb) info locals 
v = "\000\001\002\003\004\005\006\a\b\t"
(gdb) print v
$1 = "\000\001\002\003\004\005\006\a\b\t"

通过该gdb+core dump file的方法就可以大概定位到错误发生的位置了。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 17:01:25  更:2021-07-31 17:03:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 8:55:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码