在Linux上利用core dump和GDB调试
段错误(segfault)
"段错误"是程序试图操作不允许访问或试图访问的不允许内存的情况。可能导致段错误的原因主要有:
1、试图解引用空指针(你不允许访问内存地址0)
2、试图解引用不在你内存中的其他指针
3、一个C++ vtable虚表指针被破坏并指向错误的地方,这导致程序试图去执行一些不可执行的内存。
4、其他情况,比如未对齐的内存访问也可能会出现段错误。
core dump 文件
在linux下当应用程序发生异常中止退出或者发生崩溃的时候,linux内核会将应用程序在这段运行期间的内存状态等相关信息转存到磁盘,以供系统故障排查或者调试。这个转存的文件叫core dump文件。core dump文件中会记录程序当时的内存调用、堆栈引用、进程和线程调用等信息,可以帮助开发人员和维护人员了解异常发生当时的环境参数和信息,所以core dump对故障排查和bug调试具有重大的意义。
要深入探究还得利用得core dump文件,下面我们就对其进一步探究:
如何获得core dump
我们前面说了core dump是程序发生异常时候,其内存使用副本的转存文件,当你需要调试程具体序出错时的信息时候,它非常有用。
当程序发生段错误时,Linux内核有时会向磁盘写入一个core dump文件。很多人可能疑惑按照教程一步一步来做了,但是最后没有获得所需的core dump。一般情况下系统设置不输出core dump,所以没有生成core dump文件。
如果没有生成core dump文件,请按照以下步骤做设置:
1.在linux终端执行以下命令 ulimit -c unlimited
2.运行sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t
ulimit:
在linux下 通过ulimit -c设置core dump的最大值。它默认设置为0,这时候内核就不会生成core dump。它以KB为单位。 ulimit是按进程为单位进行设置的。我们可以通过运行cat /proc/PID/limit来查看具体某个进程的大小限制。
例如,这些是我的系统随便一个nginx进程的大小限制:
cat /proc/8854/limits (PID换成你系统中具体的进程号,此处我的系统中进程号位8854)
内核通过soft limit值决定写入core文件的大小 (例如上图中我们的nginx"max core file size = 0")。我们使用使用ulimit -c unlimited将软限制无限制,core dump文件就可以无限增大。我们也可以用具体文件大小来替代umlimited的值。
kernel.core_pattern
kernel.core_pattern是内核参数,通过 sysctl命令来配置,用于控制Linux内核将core dump写入磁盘的位置和文件名格式。
我们可以通过运行sysctl -a来获取当前系统的所有内核参数和设置值得列表。或者使用sysctl kernel.core_pattern仅查看kernel.core_pattern的设置值。
sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t设置下core dump文件将被写入/tmp/core-(标识进程的参数值)。具体关于%e.%p.%h参数的表示内容,请参阅man core。
Ubuntu下kernel.core_pattern设置
默认情况下,Ubuntu上, kernel.core_pattern设置的内容为:
sysctl kernel.core_pattern
kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P
这曾让我很困惑,这是什么东西,它是怎么处理我的core dump的。所以我搜索相关资料了解到:
Ubuntu使用称为"apport"的系统来记录apt包管理器中的崩溃
设置kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P
表示core dump内容被重定向到apport,其日志为/var/log/apport.log
默认情况下,apport将忽略来非Ubuntu软件包的二进制文件的那部分的崩溃日志。所以默认apport.log中默认也是不会记录core dump信息的。为了得到core dump具体做法就是重新设置kernel.core_pattern的值,将其设为sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t。
用gdb进行追踪
core dump中信息是支持用gdb做调试的,关于gdb是linux下一个强大的debug调试程序,不熟悉的同学,先搜索一下。
用下面的gdb命令打开一个core dump文件:
gdb -c my_core_file
接下来,我们想知道程序崩溃时的堆栈是什么。在gdb提示符下运行bt会给你一个堆栈追踪。默认情况下,编译时候没有做符号调试,gdb无法加载二进制符号,所以追踪结果中会都是??。如下图所示:
这种情况下,我们需要加载符号符号表,使得显示正常。可通过在gdb命令下执行:
symbol-file 应用的执行程序(绝对路径)
sharedlibrary
这会从二进制程序文件及其引入的共享库中加载符号。执行后,再次输入bt,gdb就会返回带有行号堆栈跟踪信息。
如果你想让其工作正常,在做程序做调试时候应该启用哦调试符号编译(gcc -g)。在试图找出程序崩溃的原因时,在堆栈跟踪中有行号非常有用。
在gdb也可以查看每个线程的堆栈,具体方法如下: thread apply all bt full
在Linux上利用core dump和GDB调试的更多相关文章
- 在Linux上利用core dump和GDB调试segfault
时常会遇到段错误(segfault),调试非常费劲,除了单元测试和基本测试外,有些时候是在在线环境下,没有基本开发和测试工具,这就需要调试的技能.以前介绍过使用strace进行系统调试和追踪<l ...
- linux下生成core dump文件方法及设置
linux下生成core dump文件方法及设置 from:http://www.cppblog.com/kongque/archive/2011/03/07/141262.html core ...
- 发布项目到 Linux 上运行 Core 项目
发布项目到 Linux 上运行 Core 项目 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 ASP.Net Core 给我们带来的最大的亮点就是跨平台,我在我电脑(win ...
- Visual Studio 2017 通过SSH 调试Linux 上.NET Core
Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Studio 2017 部署环境:Ubuntu ...
- Linux系统打开core dump的配置【转】
什么是core dump core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.core du ...
- Linux中生成Core Dump系统异常信息记录文件的教程
Linux中生成Core Dump系统异常信息记录文件的教程 http://www.jb51.net/LINUXjishu/473351.html
- VS2017 Linux 上.NET Core调试
调试Linux 上.NET Core Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Stud ...
- linux core dump 文件 gdb分析
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIG ...
- linux下生成core dump文件方法及设置【转】
转自:http://blog.csdn.net/mrjy1475726263/article/details/44116289 源自:http://andyniu.iteye.com/blog/196 ...
随机推荐
- (转)Python 3 collections.defaultdict() 与 dict的使用和区别
原文:https://www.cnblogs.com/herbert/archive/2013/01/09/2852843.html 在Python里面有一个模块collections,解释是数据类型 ...
- python中的sort方法
Python中的sort()方法用于数组排序,本文以实例形式对此加以详细说明: 一.基本形式 列表有自己的sort方法,其对列表进行原址排序,既然是原址排序,那显然元组不可能拥有这种方法,因为元组是不 ...
- EF基础知识小记六(使用Code First建模自引用关系,常用于系统菜单、文件目录等有层级之分的实体)
日常开发中,经常会碰到一些自引用的实体,比如系统菜单.目录实体,这类实体往往自己引用自己,所以我们必须学会使用Code First来建立这一类的模型. 以下是自引用表的数据库关系图: ok,下面开始介 ...
- 【Java并发编程】:线程中断
使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回.这 ...
- GCC 编译 Windows API 程序
前言 这学期学可视化程序设计,要使用 Windows API 绘制界面,由于笔者的笔记本硬盘太小,无法装臃肿的 VS(主要是不想装),也不想用 VC++ 6.0,所以就选用 GCC 来编译. 安装 m ...
- C++对象的内存布局以及虚函数表和虚基表
C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...
- SparkSQL简介
1.SparkSQL的发展历程 1.1 Hive and Shark SparkSQL的前身是Shark,给熟悉RDBMS但又不理解MapReduce的技术人员提供快速上手的工具,Hive应运而生,它 ...
- java字符串应用之表达式解析器
一.表达式的组成 1.数字 2.运算符:+ - / * ^ % = 3.圆括号 4.变量二.运算符优先级 由高到低分别为:+-(正负号).^.*/%.+-.= 优先 ...
- 详解ruby的attr_accessor和cattr_accessor
原文地址:http://lee2013.iteye.com/blog/1098914 1. attr_accessor的用法相当简单, 就相当于getter和setter,看一个类就知道怎样用了: c ...
- 10.Set 和 Map 数据结构
Set 和 Map 数据结构 Set 和 Map 数据结构 Set 基本用法 ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来 ...