转储及调试

来源:互联网 发布:金工 线切割编程 3b 编辑:程序博客网 时间:2024/04/29 18:03

一、概念

1. 内核转储作用

 

(1) 内核转储的最大好处是能够保存问题发生时的状态。

(2) 只要有可执行文件和内核转储,就可以知道进程当时的状态。

(3) 只要获取内核转储,那么即使没有复现环境,也能调试。

请问WIN7创建转储文件在哪?

最佳答案: 在C盘-用户-我的文档中,直接删除就行了.


如何调试?

http://www.cnblogs.com/lyhabc/articles/3751270.html


------------------------------------------------------------我是分割线---------------------------------------------------------

1、生成可调试的程序

要让程序可调试,程序执行文件中必须包含调试器必需的调试信息。不过默认情况下,GCC在编译时不会将调试信息插入到程序二进制代码中,因为这样会增加可执行文件的大小。

在编译时生成调试信息,可使用GCC的-g或者-ggdb选项,其中-g选项可以生成标准的调试信息,而-ggdb选项仅生成支持gdb调试器的调试信息。GCC在使用-g和-ggdb选项产生调试信息时,采用了分级的思路。开发人员可以通过在-g选项后附加数字1、2或3来指定在代码中加入调试信息的多少。默认的级别是2(-g2),产生的调试信息包括扩展的符号表、行号、局部或外部变量信息。级别3(-g3)包含级别2中的所有调试信息,以及源代码中定义的宏。级别1(-g1)不包含局部变量和与行号有关的调试信息,因此只能够用于回溯跟踪和堆栈转储之用。回溯跟踪指的是监视程序在运行过程中的函数调用历史,堆栈转储则是一种以原始的十六进制格式保存程序执行环境的方法,两者都是经常用到的调试手段,并在后面会详细讲述。

如果你还不会使用gcc,可以参考gcc入门。

需要注意的是,使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增加,同时增加程序在执行时的开销,因此调试选项通常仅在软件的开发和调试阶段使用。但事实上Linux中的许多软件在测试版本甚至最终发行版本中仍然使用了调试选项来进行编译,这样做的目的是鼓励用户在发现问题时自己进行调试解决,如果你不堪程序调试版本的庞大笨重,可以对其所附源代码重新优化编译。这是Linux的一个显著特色。而在Windows下,这样的特色几乎是不可能出现的,因为软件开发商认为用户对其销售的软件进行反汇编或调试是偷窃行为。天底下怎么会有这样一种逻辑呢?我买了一样东西,结果厂家说我把它打开是要触犯法律的。

2、gdb基本知识

Linux下最常用的调试器是gdb(好像是gnudebug的简写)。梁肇新说的没错,gdb是采用命令行交互方式(CUI)进行程序调试的,但它并不原始。用gdb调试程序,首先要做的是将被调试程序置入gdb为其创建的”沙箱“中。这个沙箱允许被调试程序访问内存、寄存器、和输入/输出设备,不过这些操作都在gdb的控制之下,并且调试器能够提供信息来显示程序如何访问及何时访问这些设备。

在程序执行过程的任何位置,gdb都能够停止程序并且指出源代码中相应的停止位置。当然,为了实现这一功能,gdb必须了解被调试程序的源代码,以及从哪些源代码行生成了哪些计算机指令码。因此,gdb需要被调试程序提供一些额外信息以便识别这些元素,将其与源代码进行位置匹配,这也就是为什么要在编译程序的时候使用产生调试信息选项的原因了。

程序在执行过程中停止时,gdb能够显示与被调试程序相关的任何内存区域或寄存器值,这使得程序员在被调试程序运行时能够了解程序内部运行状况,对程序进行排错。另外,gdb向程序员提供了在程序运行时改变程序变量值的途径,这使得程序员在程序运行时改动程序并且查看这些改动影响程序的输出,从而节省了源代码修改、编译到运行——这个过程的时间。

gdb能够高效完成现代C/C++调试器所能完成的任何任务,并且已经在各种项目中广为使用,因此任何人没有任何理由可以指责它原始,或者无法胜任大项目的调试工作。

3、内存转储

在程序莫明其妙地当掉之时,操作系统就会把程序当掉时的内存内容 dump 出来(现在通常是写在一个叫 core 的 file里面),以让我们或是 debugger 做为参考,这种行为名曰coredump。很多人将其翻译为“内核转储”,我觉得不通,应该叫“内存转储”,下文我将以“内存转储文件”这个名词来取代程序崩溃文件。

可能我们用的这个Linux发行版为了节约硬盘空间,默认状态下会将内存转储功能关闭了,若将其打开,需要在shell配置文件(如bash的.bash_profile)中添加:

ulimit -c unlimited

默认状态下,程序崩溃时,生成的内存转储文件位于该程序所在目录下,且名为"core.pid",pid时崩溃程序的进程号。我们可以通过修改位于/proc/sys/kernel目录下的core_uses_pid和corecore_pattern文件,来控制内存转储文件的存放位置和命名方式。

我建议的设置时去掉内存转储文件的pid,因为它只会增加字符输入工作,别无它用。另外,为了便于管理,建议将内存转储文件(去掉pid后,名为core)放在一个指定目录(譬如corefiles)下。这样在使用gdb进行调试时,只需要“gdb 程序名corefiles/core"即可。也许你觉得将内存转储文件名设置与你的程序名一致会更好一些。那么,怎样才可以实现呢,如下:

  • echo "0" > /proc/sys/kernel/core_uses_pid
  • echo "/tmp/corefiles/%e" >/proc/sys/kernel/core_pattern

上面,第一句是设置pid无效,如果将"0"设置为"1"就是让它起效。第二句中,/tmep/corefiles是内存转储文件所在目录,这里要特别注意必须首先创建这样一个目录,然后才可以在core_pattern中进行设置,不然总是无法成功的。%e是将崩溃程序名作为内存转储文件名。最后,也许你会觉得每次在使用内存转储文件都要输入其所在目录,这样很繁琐,你可以为该目录做一个环境变量,譬如$core,可以降低输入量。shell配置文件设置完毕,在shell下,"source 配置文件名",即可让其起效。

如果,想再多了解一下内存转储文件的知识,可参考这里(如果该链接无效,可以google关键字"Controlling core files“)。

内存转储功能比较有用的是使用命令”gdb 被调试程序 内存转储文件”, 进入gdb后键入bt或where命令,就可以显示出出程序是在哪一行当掉的, 还有在当掉时在哪个函数里, 这个函数是被哪个函数所调用的, 而这个调用函数又是被哪个函数所调用的....一直到 main()。根据这个信息, 可以找出五六成的 bug,不过也有例外的情况,比如本文所举的例子中有一个就属于例外。

4、gdb使用内存转储文件进行基本调试

gdb的基本语法是:

gdb [选项] [被调试程序文件 [内存转储文件]]

如果在gdb命令中指定了程序崩溃文件,可以实现不需要调试,就可以基本上分析出程序崩溃的原因了。


2. 启用内核转储

1.1 查看内核转储是否有效

在终端中输入以下命令,查看内核转储是否有效。

#ulimit -c

0

-c 表示内核转储文件的大小限制,现在显示为零,表示不能用。

可以改为1G

#ulimit -c 1073741824

也可以改为无限制

#ulimit -c unlimited

 



0 0