包含时间、行号、文件名等信息的打印

本文介绍了一种使用C语言实现的日志记录方法,通过宏定义的方式可以在代码中方便地添加debug和错误日志输出功能。这种方法不仅能够输出详细的日志信息,还能够包含文件名、函数名、行号及当前时间等元数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#define debug_out(format, ...)					\
{												\
	time_t t = time(NULL);          \
	struct tm ttt = *localtime(&t);      \
    fprintf(stdout, "["__FILE__"][%4d-%02d-%02d %02d:%02d:%02d][%s:%d] " format "\n",                     \
            ttt.tm_year + 1900, ttt.tm_mon + 1, ttt.tm_mday, ttt.tm_hour,        \
            ttt.tm_min, ttt.tm_sec, __FUNCTION__ ,  __LINE__, ##__VA_ARGS__);                            \
}

#define err_out(format, ...)					\
{												\
	time_t t = time(NULL);          \
	struct tm ttt = *localtime(&t);      \
	fprintf(stderr,"["__FILE__"][%4d-%02d-%02d %02d:%02d:%02d][%s:%d] " format ":%s\n",                     \
            ttt.tm_year + 1900, ttt.tm_mon + 1, ttt.tm_mday, \
			ttt.tm_hour, ttt.tm_min, ttt.tm_sec, \
			__FUNCTION__ ,  __LINE__,##__VA_ARGS__, \
			strerror(errno));                     \
}

 

<think>我们正在解决用户关于GDB断点显示的文件名行号不准确的问题。根据引用内容,我们可以知道: - 编译时需要添加`-g`选项来生成调试信息(引用[2]) - 断点可以通过函数名或行号设置(引用[1][2]) - 条件断点的设置(引用[3]) 问题可能的原因和解决方案: 1. **编译时未添加调试信息**:如果编译时没有使用`-g`选项,GDB将无法正确识别源代码的位置。确保编译命令包含`-g`,例如:`gcc -g test.c -o test`(引用[2])。 2. **源文件被修改**:如果设置断点后源文件被修改(比如编辑了源文件但没有重新编译),那么行号可能不再匹配。解决方案是重新编译程序。 3. **多个同名文件**:如果项目中存在多个同名文件(例如相同文件名的文件位于不同目录),GDB可能会混淆。在设置断点时使用完整路径或相对路径明确指定文件:`break /path/to/file.c:line`。 4. **优化级别过高**:编译器优化(如使用`-O2`)可能会改变代码结构,导致行号信息不准确。在调试时建议使用`-O0`(禁用优化)并加上`-g`选项。 5. **源码路径变更**:如果调试时源文件被移动或删除,GDB无法找到源文件。使用`directory`命令指定源码目录: ``` (gdb) directory /path/to/source ``` 6. **内联函数**:如果函数被内联,则断点可能不会在预期的行上停止。检查编译选项是否启用了内联(如`-O1`及以上),并尝试禁用内联或使用`-fno-inline`。 7. **断点设置在宏或头文件中**:如果断点设置在宏展开处或头文件中,可能会显示不准确的行号。使用`info macro`命令检查宏定义,并确保断点设置在正确的源文件位置。 8. **GDB版本问题**:某些GDB版本可能存在bug。尝试升级到最新版本。 9. **使用行号设置断点时行号不匹配**:有时,代码中的空行、注释行或预处理指令可能导致行号与预期不符。使用`list`命令查看实际行号。 10. **调试信息损坏**:可能是调试信息损坏,尝试重新编译并确保编译过程没有错误。 验证步骤: - 使用`info breakpoints`查看断点信息,确认断点位置(引用[1])。 - 使用`list`命令查看断点周围的代码,检查是否与预期一致(引用[1])。 如果以上方法都无法解决,可以尝试使用GDB的`info source`命令查看当前调试的源文件信息,或者使用`readelf -w`或`objdump -g`检查调试信息。 示例操作流程: 1. 编译时添加调试信息:`gcc -g -O0 test.c -o test` 2. 启动GDB:`gdb test` 3. 设置断点:`break main` 或 `break file.c:10` 4. 运行:`run` 5. 如果断点位置不正确,使用`info break`查看断点位置,然后使用`list`查看该位置代码。 6. 如果显示错误,尝试使用`directory`指定源码路径。 注意:在条件断点中,行号信息同样依赖于上述条件(引用[3])。 如果问题仍然存在,可以考虑使用更底层的调试信息,比如通过地址设置断点(`break *0x地址`),然后通过`disassemble`查看汇编代码,但这样就需要一定的汇编知识。 引用文献: [^1]: 通过函数名设置断点,会在函数的开始处停止。 [^2]: 编译时必须使用`-g`选项,否则会提示没有符号表。 [^3]: 条件断点的设置示例。 [^4]: GDB的简介。 生成相关问题: 1. 如何查看GDB中当前加载的调试信息? 2. 如何解决GDB中“No symbol table is loaded”错误? 3. 如何设置条件断点? 4. 在GDB中如何查看汇编代码? 5. 如何让GDB在断点处自动执行命令(如打印变量)?</think>### GDB断点显示文件名/行号错误的原因及解决方案 #### 常见原因分析 1. **缺少调试信息**(最常见原因) - 编译时未添加`-g`选项,导致调试信息缺失[^2] - 检查命令:`readelf -S 可执行文件 | grep debug` - 正确输出应包含`.debug_info`等段 2. **源码路径变更** - 编译后移动了源文件位置 - 编译路径与调试路径不一致(如跨机器调试) 3. **优化级别过高** - 使用`-O2`/`-O3`编译时,编译器会重组代码 - 行号映射可能被破坏(尤其是内联函数)[^3] 4. **多版本源码冲突** - 调试时加载了错误版本的源文件 - 常见于分支切换后未重新编译 5. **调试信息损坏** - 编译器生成调试信息时出错 - 二进制文件被strip等工具修改过 --- #### 解决方案 **1. 确保正确生成调试信息** ```bash # 重新编译并添加调试选项 gcc -g -O0 source.c -o program # -O0禁用优化[^2] ``` **2. 修复源码路径问题** ```bash (gdb) directory /正确/源码/路径 # 设置源码搜索路径 (gdb) show directories # 验证路径设置 ``` **3. 验证调试信息完整性** ```bash # 检查调试段是否存在 objdump -g program | grep "DW_AT_name" # 查看具体行号映射 objdump -d -S program | less ``` **4. 断点设置技巧** ```bash # 使用绝对路径设置断点 (gdb) break /绝对路径/source.c:20 # 使用函数地址验证位置 (gdb) info address main (gdb) break *0x40058f # 直接使用地址[^1] ``` **5. 调试信息修复工具** ```bash # 重建调试信息(需安装debuginfo包) eu-unstrip program.debug -o program_with_debug ``` **6. 优化问题处理** - 编译时添加`-fno-inline`禁用内联优化 - 使用`-Og`替代`-O2`(GCC 4.8+) --- #### 验证步骤 1. 编译后立即检查调试信息: ```bash gcc -g -O0 test.c -o test gdb test (gdb) break main (gdb) run (gdb) info line # 验证行号 ``` 2. 检查断点映射关系: ```bash (gdb) info breakpoints # 输出示例 Num Type Disp Enb Address What 1 break keep y 0x400543 in main at /正确路径/test.c:19 ``` 3. 反汇编验证: ```bash (gdb) disassemble /m main # 显示源码与汇编对应 ``` > **关键提示**:若使用Makefile,确保`CFLAGS`包含`-g -O0`,并执行`make clean`后再编译[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值