bug源码:
#include<myhead.h>
int main(int argc, const char *argv[]){
//智能指针demo
int num=666;
// int* p1=#
shared_ptr<int> sp1=#
cout<<*sp1<<endl;
return 0;
}
一、Bug 核心原因分析
这段代码的致命错误 是:用栈内存的地址直接初始化 shared_ptr ,违背了 shared_ptr 的设计初衷,会触发未定义行为(程序崩溃 / 段错误)。
详细拆解:
-
shared_ptr的核心职责shared_ptr是 C++ 智能指针,专门用于管理动态分配的堆内存 (通过new/malloc分配),其析构函数会自动调用delete释放所管理的指针指向的内存,避免内存泄漏。 -
代码中的内存类型问题
int num = 666;中,num是栈上的局部变量 (栈内存由操作系统自动管理,生命周期随作用域结束而销毁,不允许手动调用delete)。而shared_ptr<int> sp1 = #直接将栈内存地址交给shared_ptr管理,当sp1生命周期结束(比如函数执行完毕)时,sp1的析构函数会执行delete #------ 栈内存不允许被delete释放,这会触发未定义行为 (通常表现为程序崩溃、段错误Segmentation fault)。 -
补充:表面 "正常" 的假象代码中
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 自动管理内存的意义,实际开发中严禁这样用!
三、关键注意事项(新手必记)
shared_ptr/unique_ptr等智能指针,仅用于管理堆内存,绝对不能绑定栈内存地址;- 包含智能指针必须加头文件
<memory>,否则会编译报错; - 优先使用
make_shared创建shared_ptr,而非直接用new(减少内存泄漏风险,提升性能); - 智能指针的核心价值是 "自动释放堆内存",栈内存由系统管理,无需智能指针介入。