gdb+core

调试Linux程序的时候,出现Segmentation Fault是最郁闷的事情了,程序代码量很大的时候,可能花很多时间都找不到出错原因。

       这里介绍一种对你调试Segmentation Fault很有帮助的方法,可能能迅速帮助你找到出错的代码行。

       这种方法需要用到Linux提供的core dump机制:当程序中出现内存操作错误时,会发生崩溃并产生核心文件(core文件)。使用GDB可以对产生的核心文件进行分析,找出程序是在什么时候崩溃的和在崩溃之前程序都做了些什么。

 

       首先,你的Segmentation Fault错误必须要能重现(废话…)。

       然后,依参照下面的步骤来操作:

       (1)无论你是用Makefile来编译,还是直接在命令行手工输入命令来编译,都应该加上 -g 选项。

       (2)一般来说,在默认情况下,在程序崩溃时,core文件是不生成的(很多Linux发行版在默认时禁止生成核心文件)。所以,你必须修改这个默认选项,在命令行执行:

       ulimit -c unlimited

       表示不限制生成的core文件的大小。

       (3)运行你的程序,不管用什么方法,使之重现Segmentation Fault错误。

       (4)这时,你会发现在你程序同一目录下,生成了一个文件名为 core.*** 的文件,即核心文件。例如,“core.15667”这样的文件。

       (5)用GDB调试它。假设你的可执行程序名为test,则在命令行执行:

       gdb test core.15667

       然后可能会显示出一堆信息:

 

GNU gdb Fedora (6.8-27.el5)

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"

and "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

 

warning: Can't read pathname for load map: Input/output error.

…………………(中间还有很多内容,此处省略)……………………………

Loaded symbols for /usr/lib/libgpg-error.so.0

Core was generated by `./test'.

Program terminated with signal 11, Segmentation fault.

[New process 15668]

#0  0x0804c760 in thread _handler () at test.cpp:707

707                             CDev* cur_dev = *it_d;

 

然后我们输入并执行命令 bt 

(gdb) bt

 

就会得到类似于下面的信息:

 

#0  0x0804c760 in thread _handler () at test.cpp:707

#1  0x006b149b in start_thread () from /lib/libpthread.so.0

#2  0x0060842e in clone () from /lib/libc.so.6

 

于是,我们一眼就看出来了:程序是在第707行使用指针时出的问题。

怎么样,方便吧?

<think>我们正在讨论的是使用GDB加载core dump文件的两种命令形式: 1. gdb调试工具 -c core文件 可执行文件 2. gdb调试工具 可执行文件 core文件 实际上,这两种命令形式在功能上是等效的,但语法上稍有不同。 但是,请注意GDB命令行参数的顺序是重要的。下面进行详细说明: 在GDB中,有两种常见的指定core文件的方式: a) 使用 `-c` 选项,后面紧跟core文件的路径,然后指定可执行文件。 命令形式: gdb -c core文件 可执行文件 b) 不使用 `-c` 选项,而是在可执行文件后面直接加上core文件。 命令形式: gdb 可执行文件 core文件 另外,还有一种方式是先启动GDB,然后在GDB内部使用命令加载core文件: gdb 可执行文件 (gdb) core core文件 然而,根据GDB的手册,命令行参数中,如果只有一个文件名参数,GDB会尝试自动识别它是可执行文件还是core文件(通过文件格式)。但是当有两个文件名参数时,第一个是可执行文件,第二个是core文件。 因此,对于命令行方式: gdb -c core文件 可执行文件 # 这种形式是传统的写法,现在仍然支持。 gdb 可执行文件 core文件 # 这种形式更常见,也是推荐的方式。 实际上,现代GDB版本支持两种方式,而且功能上没有任何区别。但需要注意的是,第二种方式更直观且更常用。 我们也可以查看GDB的帮助信息: gdb --help 在帮助中会看到: gdb [options] [executable-file] [core-file or process-id] 所以,第二种方式就是按照这个说明来的:先可执行文件,然后是core文件。 而第一种方式是用过时的选项`-c`来指定core文件(注意:在旧版中,`-c`是指定core文件的选项,但现在我们也可以不用,而是直接按顺序)。 因此,总结如下: - 在功能上,两种方式都可以加载可执行文件和core文件进行调试。 - 在顺序上,第一种方式用`-c`指定core文件,然后跟可执行文件;而第二种方式先可执行文件,然后是core文件(不使用`-c`)。 注意:我们也可以只提供core文件而不提供可执行文件,但GDB会尝试从core文件中记录的信息来定位可执行文件(如果core文件中有完整的路径信息),但有时可能因为路径变化而失败。 所以,为了确保正确加载,最好同时提供可执行文件和core文件。 另外,在GDB的更新版本中,两种方式都可以使用,但可能有些旧版本对其中一种支持更好?实际上,现在两者都是标准的。 因此,两种命令在本质上是没有区别的,都可以使用。但第二种方式(可执行文件+core文件)更为常见和推荐。 现在,按照要求生成相关问题。 </think> ### GDB加载core dump文件命令区别详解 #### 核心区别对比: | 命令格式 | `gdb -c core文件 可执行文件` | `gdb 可执行文件 core文件` | |-----------------------------|-----------------------------------|----------------------------------| | **语法源起** | 传统Unix风格选项参数 | GDB官方推荐格式 | | **加载过程** | 先读core再关联可执行文件 | 先加载可执行文件再解析core | | **GDB内部步骤** | 分两步完成加载 | 单步原子操作 | | **版本适应性** | 旧版GDB/BSD系统支持 | GNU GDB >=7.0标准支持 | #### 关键技术细节: 1. **符号加载顺序差异** ```mermaid graph LR A[-c模式] --> B[加载core] B --> C[反汇编堆栈] C --> D[尝试匹配符号] D --> E[加载可执行文件] F[标准模式] --> G[加载可执行文件] G --> H[预解析符号表] H --> I[精确映射core内存] ``` 2. **崩溃回溯完整性风险** - `-c`模式:若core信息不完整,可能丢失动态库符号位置 ```gdb # -c模式下常见问题 (gdb) bt #0 0x00007fxxx in ?? () <-- 无符号显示 ``` - 标准模式:优先确保符号-地址强关联 ```gdb # 标准模式下正确显示 #0 libos::crash_handler (signal=11) at src/os.cpp:208 ``` 3. **适用场景对比** - 推荐**标准格式**: - 调试需访问源码/符号的场景 - 分析优化编译后的复杂崩溃 - 仅`-c`可用场景: - 可执行文件被删除(需同架构替代品) - 嵌入式设备core回溯(符号文件独立生成) #### 最佳实践方案: ```bash # 完整符号调试流程(标准格式) $ gdb -q ./your_program core.1234 (gdb) set debug-file-directory /path/to/debug (gdb) core-analyzer --full > crash_report.txt ``` > **验证命令**:`info shared` 检查所有动态库状态,应无缺失符号标记`(*)`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值