野指针是持有已失效地址的非空指针,常见于未初始化、释放后未置空、返回局部变量地址三种场景;预防需坚持指针初始化为nullptr、释放后立即置空、用std::unique_ptr替代裸指针、启用ASan检测。

野指针不是空指针,而是“还活着但指向废墟”的指针
野指针不是 nullptr,它通常持有某个真实地址——但该地址已失效:可能是已 delete 的堆内存、已出作用域的局部变量地址、或根本未初始化的随机值。解引用它不会立刻报错,却可能静默改写邻近内存、读到脏数据,甚至数小时后才在完全无关的代码处崩溃。
最常踩的三个坑:未初始化、释放后没置空、返回局部地址
实际项目中 90% 以上的野指针问题集中在这三类:
-
int* p;声明即危险——栈上指针不初始化就是随机值,*p = 42;直接 UB -
int* p = new int(10); delete p;之后继续用p(哪怕只判if (p)也无效,因为p非空但指向废墟) -
int* foo() { int x = 42; return &x; }——函数返回后x栈帧销毁,调用方拿到的是悬空地址
预防要从声明和释放两个动作卡死
不能靠“小心”,得靠编译器能检查、运行时能捕获的硬约束:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 所有指针声明必须初始化:
int* p = nullptr;,拒绝int* p;这种写法 -
delete p;或free(p)后紧接p = nullptr;,避免二次释放或误用 - 裸指针禁止跨函数边界传递所有权——函数要返回堆对象?改用
std::unique_ptr<int></int>;要输出值?用引用或int& out参数 - 调试阶段必加
-fsanitize=address编译,ASan 能在野指针第一次解引用时精准报错,而不是等它破坏完三页内存才崩
智能指针不是“高级技巧”,是裸指针的替代基础设施
std::unique_ptr 不是锦上添花,它是把“忘记 delete”和“重复 delete”从根源上剔除的机制:
立即学习“C++免费学习笔记(深入)”;
-
auto p = std::make_unique<int>(42);</int>—— 析构自动delete,异常安全,移动语义天然防拷贝误用 - 别对栈对象绑定
std::unique_ptr:int x = 42; auto p = std::unique_ptr<int>(&x);</int>是 UB,析构时会delete &x - 慎用
get()拿原始指针:int* raw = p.get();之后若p提前析构,raw立刻变野指针 - C 风格 API 调用需明确所有权:
some_c_api(p.release());是移交,some_c_api(p.get());是借用——后者必须确保p生命周期覆盖整个 C 函数执行期
野指针最难缠的地方不在崩溃瞬间,而在它不崩溃——你改了某行无关代码,它突然开始出错;你加了个日志,它反而不崩了。所以预防不能靠“这次我注意”,而要靠初始化、置空、智能指针、ASan 这四层物理隔离。

















