您的位置:首页 >C++日志系统宏定义实现代码
发布于2026-03-10 阅读(0)
扫一扫,手机访问
应使用带 do{...}while(0) 包裹的可变参数宏,自动注入__FILE__、__LINE__、__func__,通过std::vfprintf配合stderr实现编译期开关的日志输出,避免直接调用std::cout。

std::cout 和宏组合实现轻量日志输出直接用 std::cout 打日志太裸,没时间戳、没文件名行号、关起来麻烦。最常用做法是封装一层宏,编译期控制开关,运行时不拖慢主逻辑。
关键点在于:宏要能自动注入 __FILE__、__LINE__、__func__,还要支持像 printf 那样可变参数。C++11 起推荐用 variadic macro + std::ostringstream 或 fmt::format(若引入第三方),但纯标准库下更稳妥的是用 std::vfprintf 配合 stderr 或文件句柄。
do { ... } while(0) 包裹,避免 if/else 分支下误展开std::cout << ... << std::endl —— std::endl 强制 flush,高频日志会严重拖慢性能\n 替代 std::endl,必要时单独 flush#define LOG_INFO(fmt, ...) \
do { \
fprintf(stderr, "[%s:%d %s] " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
} while(0)__FILE__ 路径太长?用宏截取文件名部分默认 __FILE__ 展开为绝对路径(如 /home/user/project/src/log.cpp),日志里塞满冗余路径,既难读又占空间。得在宏里做字符串裁剪 —— 但 C 预处理器不支持字符串操作,所以得靠编译器扩展或运行时处理。
常见解法是用 GCC/Clang 的 __builtin_strrchr 或手动写个 basename 风格函数,但更轻量的是利用预处理器拼接:定义一个包装宏,在源文件开头用 #define THIS_FILE "log.cpp",再在日志宏里用 THIS_FILE。不过这要求每个文件手动加,易漏。
std::string_view(__FILE__).substr(...).data() 在运行时截取,只在 debug 日志启用(不影响 release 性能)#define SHORT_FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__),然后在日志宏里用 SHORT_FILEstrrchr 是 C 标准函数,需包含 <cstring>,且不是 constexpr,不能用于 static_assertNDEBUG 或自定义开关宏线上环境通常完全禁用调试日志,但又不能把所有 LOG_DEBUG 行注释掉。最干净的方式是依赖编译宏控制是否展开。
#ifdef DEBUG_LOG 包裹整条日志语句,未定义时宏展开为空 —— 无任何运行时开销if (g_log_enabled) { LOG(...) },即使 flag 为 false,参数表达式仍会求值(比如 LOG("val=%d", expensive_func()) 会白调一次)LOG_LEVEL 设为 0~3,宏内部用 if constexpr(C++17)或模板特化跳过低优先级日志的展开#ifdef ENABLE_LOG
# define LOG_DEBUG(fmt, ...) LOG_INFO(fmt, ##__VA_ARGS__)
#else
# define LOG_DEBUG(fmt, ...) do {} while(0)
#endiffprintf 安全吗?要不要加锁?fprintf(stderr, ...) 在多数 libc 实现中是线程安全的(内部有锁),但不保证原子性 —— 两行日志内容可能交叉(如 A 线程打一半,B 线程插进来,最后输出乱序)。对调试够用,但审计或追踪类日志不行。
真正需要顺序一致,就得自己加锁,或改用线程局部缓冲 + 定期刷出。不过锁本身有开销,尤其高并发场景。
std::mutex 全局锁 + std::lock_guard,锁粒度控制在单次 fwrite 内__thread(GCC)或 thread_local 缓冲区,每个线程攒几条再批量写,减少系统调用std::cout 默认也是线程安全的,但同样不保证跨行原子性;且它比 fprintf 多一层 streambuf 抽象,略慢printf 替代 fprintf(stderr, ...) —— stdout 可能被重定向或行缓冲,日志卡住不输出日志宏看着简单,但文件名截取、线程安全、编译开关和参数求值时机这四点,任何一个没压住,上线后都可能变成隐性性能瓶颈或排查盲区。
上一篇:163邮箱注销方法及永久关闭流程
下一篇:风车动漫汉化官网地址分享
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9