“Conditional jump or move depends on uninitialised value(s)”表示代码中if、while等条件判断依赖了未初始化变量,行为不可预测;必须加--track-origins=yes和-g编译才能精确定位源头。

Conditional jump depends on uninitialised value 是什么
这不是崩溃,而是 Valgrind 在告诉你:某处 if、while、for 或三目运算符的判断逻辑,依赖了一个**未初始化的变量值**。C/C++ 中局部变量(尤其是栈上分配的)默认不为零,其内容是随机残留数据;用它做条件跳转,行为不可预测,可能在不同机器/编译器下表现不一致,甚至掩盖更深层 bug。
--track-origins=yes 是必须加的参数
不加这个,Valgrind 只会报类似:
==12345== Conditional jump or move depends on uninitialised value(s) ==12345== at 0x40118A: process_data (main.cpp:23)
你只知道第 23 行有问题,但不知道那个“未初始化的变量”是从哪来的。加了之后,它会多打一段溯源信息:
==12345== Uninitialised value was created by a stack allocation ==12345== at 0x401120: main (main.cpp:10)
这说明第 10 行定义了一个未初始化的局部变量(比如 int flag;),然后在第 23 行被拿去判断。
- 必须配合
-g编译,否则行号无法对应 - 如果程序用了
-O2或更高优化等级,变量可能被寄存器优化掉,--track-origins=yes会失效或报错——此时要切回-O0 - 第三方库(如 zlib、OpenSSL)内部也可能触发该警告,但往往只是字节对齐填充所致;可先用
--suppressions=/usr/lib/valgrind/default.supp过滤
常见真实场景和检查点
这类警告多数不是“写错了”,而是“忘了赋初值”。重点关注以下几类代码:
-
struct或class实例声明后未调用构造函数或未显式初始化成员,例如Config cfg;而cfg.timeout是int类型且无默认值 - 用
malloc分配内存但没memset,后续又用其中某个字段做判断(new不会这样,但malloc会) - 函数返回
int*或结构体指针,调用方未检查是否为nullptr就直接解引用并用于条件分支 - 数组越界读取导致读到栈上垃圾值,再拿这个值做
if (buf[i] == 0)判断
为什么 still reachable 和 possibly lost 不是源头
Conditional jump 错误和内存泄漏类型无关——它不关心你有没有 free,只关心你有没有给变量一个确定的值。所以看到报告里同时有 still reachable(全局容器未清空)或 possibly lost(循环引用等),别被带偏。它们各自独立,应分开处理。真正要盯死的,只有 definitely lost 和所有以 Invalid read/write、Conditional jump、Use of uninitialised value 开头的条目。


















