智能指针使用bug

bug源码:

复制代码
#include<myhead.h>
int main(int argc, const char *argv[]){
 
    //智能指针demo
    int num=666;

    // int* p1=&num;

    shared_ptr<int> sp1=&num;

    cout<<*sp1<<endl;


    return 0;
}

一、Bug 核心原因分析

这段代码的致命错误 是:用栈内存的地址直接初始化 shared_ptr ,违背了 shared_ptr 的设计初衷,会触发未定义行为(程序崩溃 / 段错误)。

详细拆解:
  1. shared_ptr 的核心职责shared_ptr 是 C++ 智能指针,专门用于管理动态分配的堆内存 (通过 new/malloc 分配),其析构函数会自动调用 delete 释放所管理的指针指向的内存,避免内存泄漏。

  2. 代码中的内存类型问题int num = 666; 中,num栈上的局部变量 (栈内存由操作系统自动管理,生命周期随作用域结束而销毁,不允许手动调用 delete)。而 shared_ptr<int> sp1 = &num; 直接将栈内存地址交给 shared_ptr 管理,当 sp1 生命周期结束(比如函数执行完毕)时,sp1 的析构函数会执行 delete &num; ------ 栈内存不允许被 delete 释放,这会触发未定义行为 (通常表现为程序崩溃、段错误 Segmentation fault)。

  3. 补充:表面 "正常" 的假象代码中 cout << *sp1 << endl; 可能暂时打印出 666,但这只是巧合(此时 sp1 还未析构,栈内存仍有效),本质是严重的内存管理错误,程序运行到 sp1 析构时必然出错。

二、Bug 解决方案(分场景给出最优写法)

场景 1:管理 "动态分配的堆内存"(推荐,符合 shared_ptr 设计初衷)

shared_ptr 应管理堆内存,需通过 new 分配内存后初始化,或用更安全的 make_shared(C++11 及以上)。

方案 1:用 new 初始化 shared_ptr

cpp

运行

复制代码
#include <iostream>
#include <memory> // 必须包含智能指针头文件
using namespace std;

int main() {
    // 1. 动态分配堆内存(int值为666)
    int* p_num = new int(666);
    // 2. 用堆内存地址初始化shared_ptr(正确)
    shared_ptr<int> sp1(p_num);
    
    cout << *sp1 << endl; // 输出:666
    
    // 无需手动delete,sp1析构时会自动delete p_num
    return 0;
}
方案 2:用 make_shared 初始化(更优,避免裸指针)

make_shared 是 C++11 引入的推荐写法,直接分配堆内存并构造 shared_ptr,避免裸指针暴露,降低内存泄漏风险:

cpp

运行

复制代码
#include <iostream>
#include <memory>
using namespace std;

int main() {
    // 直接创建管理堆内存的shared_ptr(推荐)
    shared_ptr<int> sp1 = make_shared<int>(666);
    
    cout << *sp1 << endl; // 输出:666
    
    return 0;
}
场景 2:非要管理栈变量(不推荐,仅作知识补充)

如果确实需要让 shared_ptr 指向栈变量(无实际业务意义,违背设计初衷),需自定义空删除器 (告诉 shared_ptr 析构时不执行 delete):

cpp

运行

复制代码
#include <iostream>
#include <memory>
using namespace std;

int main() {
    int num = 666;
    // 自定义删除器:空函数(不做任何操作)
    auto no_op_delete = [](int*) {};
    // 用空删除器初始化shared_ptr,避免析构时delete栈内存
    shared_ptr<int> sp1(&num, no_op_delete);
    
    cout << *sp1 << endl; // 输出:666
    
    // sp1析构时调用no_op_delete,不会执行delete,避免崩溃
    return 0;
}

⚠️ 注意:此方案仅为 "规避崩溃",但失去了 shared_ptr 自动管理内存的意义,实际开发中严禁这样用

三、关键注意事项(新手必记)

  1. shared_ptr/unique_ptr 等智能指针,仅用于管理堆内存,绝对不能绑定栈内存地址;
  2. 包含智能指针必须加头文件 <memory>,否则会编译报错;
  3. 优先使用 make_shared 创建 shared_ptr,而非直接用 new(减少内存泄漏风险,提升性能);
  4. 智能指针的核心价值是 "自动释放堆内存",栈内存由系统管理,无需智能指针介入。
相关推荐
2401_892070981 天前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei1 天前
Visual Studio 配置C++opencv
c++·学习·visual studio
小O的算法实验室1 天前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
不爱吃炸鸡柳1 天前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发1 天前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
‎ദ്ദിᵔ.˛.ᵔ₎1 天前
STL 栈 队列
开发语言·c++
2401_892070981 天前
【Linux C++ 日志系统实战】高性能文件写入 AppendFile 核心方法解析
linux·c++·日志系统·文件写对象
郭涤生1 天前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿1 天前
vector
c语言·开发语言·数据结构·c++·算法
cccyi71 天前
【C++ 脚手架】etcd 的介绍与使用
c++·服务发现·etcd·服务注册