需要注释掉原有的 av_log
声明和实现,然后将新代码添加到 log.h
中。以下是完整、优化的实现方案:
在log.h中添加一下代码,已定义新的av_log函数。
// log.h
#include <stdio.h>
// 修改函数签名,增加 file 和 line 参数
static void av_log_impl(void* avcl, int level, const char *file, int line, const char *fmt, ...) {
va_list vl;
va_start(vl, fmt);
// 动态拼接调用位置信息(避免缓冲区溢出)
char new_fmt[1024];
snprintf(new_fmt, sizeof(new_fmt), "[%s:%d] %s", file, line, fmt);
av_vlog(avcl, level, new_fmt, vl); // 调用底层日志函数
va_end(vl);
}
// 定义包装宏:在调用点展开 __FILE__ 和 __LINE__
#define av_log(avcl, level, fmt, ...) \
av_log_impl(avcl, level, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
需要同时进行的修改:
在实现文件中注释掉原有函数定义:
在你的实现文件(如 log.c)中找到原函数并注释掉:// void av_log(void* avcl, int level, const char *fmt, ...) // { // ... 原有实现 ... // }
注释掉原来的av_log声明:
在 log.h 中,注释掉原来的av_log声明:// 注释掉原来的av_log声明 // void av_log(void* avcl, int level, const char *fmt, ...);
确保 av_vlog 可用:
确保在 log.h 中声明了av_vlog
函数:void av_vlog(void* avcl, int level, const char *fmt, va_list vl);
关键优化说明:
安全缓冲区:
- 使用固定大小缓冲区避免动态内存分配
- 安全截断确保不会越界 (snprintf 的自动截断特性)
性能考虑:
static
函数定义避免符号冲突- 内联调用位置信息仅在启用日志时才处理
编译器兼容性:
##__VA_ARGS__
处理 GNU C/C++ 的空参数情况- 使用标准 C99 特性保证可移植性
日志格式灵活性:
如果想添加更多上下文(如函数名),可扩展为:#define av_log(avcl, level, fmt, ...) \ av_log_impl(avcl, level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
然后在函数中修改格式字符串为
"[%s:%d] %s: %s"
这样修改后,所有调用
av_log
的地方都会自动添加准确的位置信息,例如:av_log(NULL, 1, "Starting playback"); // 输出格式: [player.c:42] Starting playback