段错误(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调试的更多相关文章

  1. 在Linux上利用core dump和GDB调试segfault

    时常会遇到段错误(segfault),调试非常费劲,除了单元测试和基本测试外,有些时候是在在线环境下,没有基本开发和测试工具,这就需要调试的技能.以前介绍过使用strace进行系统调试和追踪<l ...

  2. linux下生成core dump文件方法及设置

    linux下生成core dump文件方法及设置    from:http://www.cppblog.com/kongque/archive/2011/03/07/141262.html core ...

  3. 发布项目到 Linux 上运行 Core 项目

    发布项目到 Linux 上运行 Core 项目 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 ASP.Net Core 给我们带来的最大的亮点就是跨平台,我在我电脑(win ...

  4. Visual Studio 2017 通过SSH 调试Linux 上.NET Core

    Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Studio 2017 部署环境:Ubuntu ...

  5. Linux系统打开core dump的配置【转】

    什么是core dump core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.core du ...

  6. Linux中生成Core Dump系统异常信息记录文件的教程

    Linux中生成Core Dump系统异常信息记录文件的教程 http://www.jb51.net/LINUXjishu/473351.html

  7. VS2017 Linux 上.NET Core调试

    调试Linux 上.NET Core Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Stud ...

  8. linux core dump 文件 gdb分析

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

  9. linux下生成core dump文件方法及设置【转】

    转自:http://blog.csdn.net/mrjy1475726263/article/details/44116289 源自:http://andyniu.iteye.com/blog/196 ...

随机推荐

  1. 【数组】Container With Most Water

    题目: Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, a ...

  2. [转发] win8安装mindget mindmanger

    win8安装mindget mindmanger   1安装MindManager时,显示安装Visual C++ 2005 Redistributable时报错  解决方法:1.把安装程序移动到没有 ...

  3. 【原】中文Ubuntu主目录下的文档文件夹改回英文

    想把中文Ubuntu主目录下的文档文件夹改回英文,在Terminal下面操作的时候要输入中文特别不方便,于是便用了更改名字的想法 方法一: 首先把那几个中文名称修改成相应的英文,比如 Desktop. ...

  4. java8 学习之路之lambda

    前言 目前我们知道java的版本已经发布到12了,之前的项目用的是JDK1.7,听说JDK1.8的改动相对来说大一些,因此抽空学学JDK1.8的一些新特性.本人也是通过阅读Java8实战这本书做一些小 ...

  5. chroot的用法

    chroot命令用来在指定的根目录下运行指令.chroot,即 change root directory (更改 root 目录).在 linux 系统中,系统默认的目录结构都是以/,即是以根 (r ...

  6. 使用DataTrigger来代替Triggerr

    普通的Trigger监听鼠标移入的代码如下: <Trigger Property="IsMouseOver" Value="true">     & ...

  7. PHP在使用正则表达式验证,防注入的时候要注意一下的细节

    如下:这是一个防止用户输入的数据中包含SQL的一些关键字的正则表达式 之前一直认为这写的很正确,没多大的问题,而且自己测试也没问题, 因为关键字包含 And,而如果用户输入andy的时候呢,汗,所以还 ...

  8. Spring的@Scheduled任务调度

    一. 定时任务实现方式 定时任务实现方式: Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行 ...

  9. Autofac--手动依赖注入

    本文只适合初步接触 autoafc 的小白,大佬勿喷. autofac是一种很轻量的一个依赖注入容器 暂时先说一下手动注入的方式(因为使用自动注入遇到了坑,暂时先写一下手动注入) 1.先定义接口 pu ...

  10. resize定义元素尺寸大小

    为了增强用户体验,CSS3增加了很对的新属性,其中一个重要的属性就是resize,它允许用户通过拖动的方式改变元素的尺寸,到目前为止,主要用于可以使用overtflow属性的任何容器元素中 resiz ...