[Linux] 什么是 段错误(吐核)?

段错误

我们在Linux环境下编程中,有时执行编译好的文件时会出现段错误(吐核),这是经常出现的一个错误。


它是什么意思呢? 这个错误过程中都有哪些文件? 与VS中IDE直接报错有何不同?我们将通过本篇进行探讨。

 

  • 查阅相关文档发现,产生段错误的原因主要有:
  1. 解引用空指针
  2. 访问不可访问的内存空间(如内核空间)
  3. 访问不存在的内存地址
  4. 试图写一个只读内存空间(如代码段)
  5. 栈溢出(函数递归调用)
  6. 使用未初始化的指针(定义时没有初始化或者已经回收)

比如我们在程序中 对一个空指针进行解引用 进行演示:

这里就出现了如开头第一张图中所示的段错误(吐核)

吐核:吐出了一个“核心转储文件”coredump文件
  
  程序确认出现错误时的“临终遗言” 写入核心转储文件,也是使用gdb调试器最常用到的场景

  • 那么如何查看吐出的 核心转储文件?

  我们尝试ls -a查看全部文件 (包含默认隐藏的文件)发现也并没有相关的新文件产生。【失败】

  • 其实操作系统有限制,默认不允许随意吐核,在一个工程中coredump文件有可能会特别大,多次吐核过于占存,这样随意吐核会影响机器性能,一定要慎用。

文件什么样?

我们通过指令查看与程序相关的属性,其中会包含核心转储文件信息:

ulimit -a

第一条core file就是coredump—— 核心转储文件,size0表示不允许吐核,更改一下文件大小就可以顺利产出吐核文件了。

● 通过指令更改为大小为无限制

ulimit -c unlimited

我们再执行./hello,再次吐核。
之后 ls 就会出现core.3616文件,数字后缀不同机器会不一样,这个不用在意。这个就是核心转储文件,我们成功通过操作查看到了。

仔细查看文件详情,发现文件确实占存很大:

那么我们通过vim进入文件内部,看看它究竟是什么样子的:

果然如我们所料看不太懂,不知所云,这时候就借助我们老搭档gdb调试器的力量,输入指令:

gdb  可执行文件名 + 核心转储文件名
核心转储文件通过不同的可执行文件可能吐出不同的核,所以要带上可执行文件名,告诉操作系统这个核心转储文件是哪个可执行文件吐出的。

在这个程序中我们就输入gdb main core.3616,回车后就可以定位程序错误原因了:

错误原因

  • 红色方框中显示了在main.c文件中的Add函数中第6行对应的*p = 100;这句代码有问题,导致程序异常终止,因为空指针不能解引用。
  • 蓝色方框是一个比较重要的概念,11号信号,它是段错误(Segmentation fault)的典型图腾。

调用情况

那么这错误的第6行代码到底是怎么执行的?
  可以通过bt指令查看函数调用栈:
  

所以是因为main函数调用Add函数再调用Add2函数,就在第6行出现了错误。这就是它的调用情况。

小结
其实段错误就是:

硬件设备MMU发现访问了一个非法的虚拟地址,通知操作系统内核给进程发送11号信号,进程收到了一个11号信号,导致进程异常终
--------------------- 
作者:giturtle 
来源:优快云 
原文:https://blog.youkuaiyun.com/qq_42351880/article/details/85332621 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值