集团主站
欢迎来到成都达内官方网站!达内—美国上市公司 亿元级外企IT培训企业!
成都it培训哪家好
成都it培训哪家好
全国服务监督电话:15023458194  |   联系客服   |
当前位置:主页 > 培训课程 > Linux >

成都云计算培训班:如何在Linux上获得错误段的核心转储

发布者: 成都云计算培训机     浏览次数:     发布时间:2018-07-24 10:59:04

今天小编要跟大家分享的文章是关于Linux上错误段的核心转储问题...

       今天小编要跟大家分享的文章是关于Linux上错误段的核心转储问题。喜欢Linux操作系统,对Linux感兴趣的小伙伴快来看一看吧,希望通过本篇文章能够有所收获。

        成都云计算培训班
  首先我们来说一说什么是段错误?


  “段错误(segmentation fault)”是指你的程序尝试访问不允许访问的内存地址的情况。这可能是由于:

        成都云计算工程师
  试图解引用空指针(你不被允许访问内存地址 0);? 试图解引用其他一些不在你内存(LCTT 译注:指不在合法的内存地址区间内)中的指针;? 一个已被破坏并且指向错误的地方的 C++ 虚表指针(C++ vtable pointer),这导致程序尝试执行没有执行权限的内存中的指令;? 其他一些我不明白的事情,比如我认为访问未对齐的内存地址也可能会导致段错误(LCTT 译注:在要求自然边界对齐的体系结构,如 MIPS、ARM 中更容易因非对齐访问产生段错误)。


  这个“C++ 虚表指针”是我的程序发生段错误的情况。我可能会在未来的博客中解释这个,因为我最初并不知道任何关于 C++ 的知识,并且这种虚表查找导致程序段错误的情况也是我所不了解的。


  如何在Linux上获得错误段的核心转储


  下面我们就来看一看如何得到一个核心转储?


  步骤1:运行 valgrind


  我发现找出为什么我的程序出现段错误的最简单的方式是使用 valgrind:我运行

        成都云计算培训机构
  1. valgrind -v your-program


  这给了我一个故障时的堆栈调用序列。 简洁!


  但我想也希望做一个更深入调查,并找出些 valgrind 没告诉我的信息! 所以我想获得一个核心转储并探索它。


  如何获得一个核心转储


  核心转储(core dump)是您的程序内存的一个副本,并且当您试图调试您的有问题的程序哪里出错的时候它非常有用。


  当您的程序出现段错误,Linux 的内核有时会把一个核心转储写到磁盘。 当我最初试图获得一个核心转储时,我很长一段时间非常沮丧,因为 - Linux 没有生成核心转储!我的核心转储在哪里?


  这就是我最终做的事情:


  ☉ 在启动我的程序之前运行 ulimit -c unlimited☉ 运行 sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t


  ulimit:设置核心转储的最大尺寸


  ulimit -c 设置核心转储的最大尺寸。 它往往设置为 0,这意味着内核根本不会写核心转储。 它以千字节为单位。 ulimit 是按每个进程分别设置的 —— 你可以通过运行 cat /proc/PID/limit 看到一个进程的各种资源限制。


  例如这些是我的系统上一个随便一个 Firefox 进程的资源限制:


  1. $ cat /proc/6309/limits


  2. Limit Soft Limit Hard Limit Units


  3. Max cpu time unlimited unlimited seconds


  4. Max file size unlimited unlimited bytes


  5. Max data size unlimited unlimited bytes


  6. Max stack size 8388608 unlimited bytes


  7. Max core file size 0 unlimited bytes


  8. Max resident set unlimited unlimited bytes


  9. Max processes 30571 30571 processes


  10. Max open files 1024 1048576 files


  11. Max locked memory 65536 65536 bytes


  12. Max address space unlimited unlimited bytes


  13. Max file locks unlimited unlimited locks


  14. Max pending signals 30571 30571 signals


  15. Max msgqueue size 819200 819200 bytes


  16. Max nice priority 0 0


  17. Max realtime priority 0 0


  18. Max realtime timeout unlimited unlimited us


  内核在决定写入多大的核心转储文件时使用软限制(soft limit)(在这种情况下,max core file size = 0)。 您可以使用 shell 内置命令 ulimit(ulimit -c unlimited) 将软限制增加到硬限制(hard limit)。


  kernel.core_pattern:核心转储保存在哪里


  kernel.core_pattern 是一个内核参数,或者叫 “sysctl 设置”,它控制 Linux 内核将核心转储文件写到磁盘的哪里。


  内核参数是一种设定您的系统全局设置的方法。您可以通过运行 sysctl -a 得到一个包含每个内核参数的列表,或使用 sysctl kernel.core_pattern 来专门查看 kernel.core_pattern 设置。


  所以 sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t 将核心转储保存到目录 /tmp 下,并以 core 加上一系列能够标识(出故障的)进程的参数构成的后缀为文件名。


  如果你想知道这些形如 %e、%p 的参数都表示什么,请参考 man core[1]。


  有一点很重要,kernel.core_pattern 是一个全局设置 —— 修改它的时候最好小心一点,因为有可能其它系统功能依赖于把它被设置为一个特定的方式(才能正常工作)。


  kernel.core_pattern 和 Ubuntu


  默认情况下在 ubuntu 系统中,kernel.core_pattern 被设置为下面的值:


  1. $ sysctl kernel.core_pattern


  2. kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P


  这引起了我的迷惑(这 apport 是干什么的,它对我的核心转储做了什么?)。以下关于这个我了解到的:


  ? Ubuntu 使用一种叫做 apport 的系统来报告 apt 包有关的崩溃信息。? 设定 kernel.core_pattern=|/usr/share/apport/apport %p %s %c %d %P 意味着核心转储将被通过管道送给 apport 程序。? apport 的日志保存在文件 /var/log/apport.log 中。? apport 默认会忽略来自不属于 Ubuntu 软件包一部分的二进制文件的崩溃信息


  我最终只是跳过了 apport,并把 kernel.core_pattern 重新设置为 sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t,因为我在一台开发机上,我不在乎 apport 是否工作,我也不想尝试让 apport 把我的核心转储留在磁盘上。


  现在你有了核心转储,接下来干什么?


  好的,现在我们了解了 ulimit 和 kernel.core_pattern ,并且实际上在磁盘的 /tmp 目录中有了一个核心转储文件。太好了!接下来干什么?我们仍然不知道该程序为什么会出现段错误!


  下一步将使用 gdb 打开核心转储文件并获取堆栈调用序列。


  从 gdb 中得到堆栈调用序列


  你可以像这样用 gdb 打开一个核心转储文件:


  1. $ gdb -c my_core_file


  接下来,我们想知道程序崩溃时的堆栈是什么样的。在 gdb 提示符下运行 bt 会给你一个调用序列(backtrace)。在我的例子里,gdb 没有为二进制文件加载符号信息,所以这些函数名就像 “??????”。幸运的是,(我们通过)加载符号修复了它。


  下面是如何加载调试符号。


  1. symbol-file /path/to/my/binary


  2. sharedlibrary


  这从二进制文件及其引用的任何共享库中加载符号。一旦我这样做了,当我执行 bt 时,gdb 给了我一个带有行号的漂亮的堆栈跟踪!


  如果你想它能工作,二进制文件应该以带有调试符号信息的方式被编译。在试图找出程序崩溃的原因时,堆栈跟踪中的行号非常有帮助。:)


  查看每个线程的堆栈


  通过以下方式在 gdb 中获取每个线程的调用栈!


  1. thread apply all bt full


  gdb + 核心转储 = 惊喜


  如果你有一个带调试符号的核心转储以及 gdb,那太棒了!您可以上下查看调用堆栈(LCTT 译注:指跳进调用序列不同的函数中以便于查看局部变量),打印变量,并查看内存来得知发生了什么。这是最好的。


  如果您仍然正在基于 gdb 向导来工作上,只打印出栈跟踪与bt也可以。


  ASAN


  另一种搞清楚您的段错误的方法是使用 AddressSanitizer 选项编译程序(“ASAN”,即 $CC -fsanitize=address)然后运行它。 本文中我不准备讨论那个,因为本文已经相当长了,并且在我的例子中打开 ASAN 后段错误消失了,可能是因为 ASAN 使用了一个不同的内存分配器(系统内存分配器,而不是 tcmalloc)。


  在未来如果我能让 ASAN 工作,我可能会多写点有关它的东西。(LCTT 译注:这里指使用 ASAN 也能复现段错误)


  从一个核心转储得到一个堆栈跟踪真的很亲切!


  这个博客听起来很多,当我做这些的时候很困惑,但说真的,从一个段错误的程序中获得一个堆栈调用序列不需要那么多步骤:


  ☉ 试试用 valgrind


  如果那没用,或者你想要拿到一个核心转储来调查:


  ☉ 确保二进制文件编译时带有调试符号信息;☉ 正确的设置 ulimit 和 kernel.core_pattern;☉ 运行程序;☉ 一旦你用 gdb 调试核心转储了,加载符号并运行 bt;☉ 尝试找出发生了什么!


  我可以使用 gdb 弄清楚有个 C++ 的虚表条目指向一些被破坏的内存,这有点帮助,并且使我感觉好像更懂了 C++ 一点。也许有一天我们会更多地讨论如何使用 gdb 来查找问题!


  以上就是小编今天为大家分享的文章,希望本篇文章能够对喜欢Linux的小伙伴们带来一些收获,想要了解更多关于Linux的相关资讯记得关注达内Linux培训官网。
(责任编辑:陈老师)
最新开班
  • 成都Java培训班
    免费试听名额发放中...
  • 成都C++培训班
    免费试听名额发放中...
  • 成都PHP培训班
    免费试听名额发放中...
  • 成都网络工程培训班
    免费试听名额发放中...
  • 成都Unity3D培训班
    免费试听名额发放中...
  • 成都大数据培训班
    免费试听名额发放中...
  • 成都uid培训班
    免费试听名额发放中...
  • 成都会计培训班
    免费试听名额发放中...
  • 成都Python培训班
    免费试听名额发放中...
  • 成都嵌入式培训班
    免费试听名额发放中...
  • 成都web培训班
    免费试听名额发放中...
  • 成都软件测试培训班
    免费试听名额发放中...
在线留言
提交

校区地址:绵阳市涪城区临园路东段68号富临大都会7栋3单元9层12号

联系电话:15023458194

公交路线:富乐路口凯德广场(10路;29路;3路;15路;11路;15a路;71路)

校区地址:成都市锦江区东大街紫东楼段35号明宇金融广场19楼1903室

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市高新区奥克斯广场蜀锦路209号一楼商铺

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都锦江区东大街芷泉街229号东方广场C座3楼303

联系电话:15023458194

公交路线:芷泉街(188路;115路;515路;236路;505路;501路;84路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市武侯区佳灵路3号红牌楼广场2号写字楼11楼1115号

联系电话:15023458194

公交路线:红牌楼东(11路;92路;100路;111路;139路;g28路;快速公交K1/K2) 地铁路线:红牌楼站(地铁3号线)

校区地址:成都市锦江区红星路二段70号四川日报大厦502-2

联系电话:15023458194

公交路线:市二医院站(6路;49路;102路;5路;37路;g92路;) 地铁路线:地铁市二医院(地铁3号线)

校区地址:成都市锦江区东大街紫东段35号明宇广场2306

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:四川省成都市武侯区高新科技孵化园9号园区E座7楼

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都市成华区建设路10号万科钻石广场B座5楼

联系电话:15023458194

公交路线:建设路中(6路;14路;42路;72路;76路;1010路;)

校区地址:成都市高新区奥克斯广场B座1708

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

了解达内动态
关注成都达内教育公众号

首页 | 关于达内 | 课程中心 | 专家师资 | 视频教程 | 学员空间 | 校企合作 | 新闻资讯 | 就业指导 | 网站地图

20016-2025 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56