gflags 中需用 define_* 宏在全局作用域定义 flag 变量,如 define_bool(verbosity, false, "enable verbose logging"),变量名为 flags_verbosity;须调用 parsecommandlineflags 解析命令行参数。

gflags 中如何定义 flag 变量(C++)
gflags 的 flag 变量不是普通变量,必须用 DEFINE_* 宏在全局作用域声明,且每个 flag 名在进程内必须唯一。未用宏定义的变量不会被 gflags 解析,也不会出现在 --help 输出中。
常见类型宏包括:DEFINE_bool、DEFINE_int32、DEFINE_string、DEFINE_double 等。所有宏接受三个参数:flag 名、默认值、说明字符串。
DEFINE_bool(verbosity, false, "Enable verbose logging"); DEFINE_int32(port, 8080, "Server listening port"); DEFINE_string(config_path, "/etc/app.conf", "Path to config file");
注意:DEFINE_string 的默认值不能是空指针或临时字符串字面量(如 "" 是安全的,但 std::string().c_str() 不行);DEFINE_bool 默认值必须是字面量 true 或 false,不能是整数 0/1。
如何在代码中访问和修改已定义的 flag
定义后,对应变量会以全局符号形式存在,命名规则为 FLAGS_ + flag 名,例如 FLAGS_verbosity、FLAGS_port。直接读写即可,无需额外声明。
但要注意:gflags 不提供线程安全的读写封装,多线程同时修改同一 flag 可能导致未定义行为;读取操作通常是安全的,但若 flag 被其他线程正在解析(如 ParseCommandLineFlags 执行中),应避免并发访问。
- 读取:
if (FLAGS_verbosity) { ... } - 运行时修改:
FLAGS_port = 9090;(后续逻辑会看到新值) - 重置为默认值:
gflags::SetCommandLineOption("port", "8080");(该函数返回是否成功)
ParseCommandLineFlags 必须在 main 开头调用
ParseCommandLineFlags 是解析入口,它会扫描 argv,匹配 --flag_name=value 或 --flag_name(对 bool 类型),并更新对应 FLAGS_* 变量。不调用它,命令行参数完全不会生效。
典型用法:
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true); // 第三个参数为 true 表示移除已解析的 flag 参数
// 此后 FLAGS_* 已更新
if (FLAGS_verbosity) {
LOG(INFO) <p>容易踩的坑:</p>
- 传入的
&argc和&argv必须是非 const 指针,且argv内存需可写(某些嵌入式环境或沙箱可能限制) - 第三个参数设为
false时,argv不会被修改,但ParseCommandLineFlags仍会跳过 flag 参数——此时后续逻辑若依赖原始argv[1]可能出错 - 如果程序有自定义参数预处理(如识别
--version后提前退出),必须在ParseCommandLineFlags之前做,否则 flag 解析失败或干扰判断
常见错误:flag 未定义却尝试设置或读取
典型报错:undefined reference to `FLAGS_foo'(链接错误)或运行时报 Unknown command line flag 'foo'(解析错误)。根本原因是:flag 名拼写不一致,或在多个编译单元中重复定义(违反 ODR),或忘记包含定义它的 .cc 文件。
调试建议:
- 检查所有
DEFINE_*宏是否都在 .cc 文件里(不能放在头文件中,除非加static,但那样无法跨文件访问) - 确认链接时包含了定义 flag 的目标文件
- 用
gflags --help | grep foo验证 flag 是否被注册(需确保程序至少执行过一次ParseCommandLineFlags) - bool flag 误写成
--foo=true:gflags 接受--foo、--foo=true、--foo=false,但--foo=1会报错
最隐蔽的问题是:同一个 flag 在两个不同 .cc 文件里各 DEFINE 了一次,链接器可能静默选一个,导致行为不可预测。











