Boost.auto_ptr的实现源码

本文探讨了智能指针的概念,特别是Boost库中的auto_ptr,它用于动态对象的生命周期管理,防止内存泄漏。通过引用计数,auto_ptr能确保正确销毁对象。智能指针重载了->和*操作符,并在析构时自动释放内存。文中还提及了智能指针的其他功能,如复制行为和所有权转移。

   智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。它的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
   
智能指针就是模拟指针动作的类。所有的智能指针都会重载 -> * 操作符。智能指针还有许多其他功能,比较有用的是自动销毁。这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。当然,智能指针还不止这些,还包括复制时可以修改源对象等。智能指针根据需求不同,设计也不同(写时复制,赋值即释放对象拥有权限、引用计数等,控制权转移等)。auto_ptr 即是一种常见的智能指针。


//声明文件

#pragma once

//智能指针
template<class T>
class CSmartPtr
{
	T* m_pointer;
public://构造之后析构之前使用计数
	CSmartPtr(T* p = NULL);
	CSmartPtr(const CSmartPtr<T>& obj);
	~CSmartPtr();

	CSmartPtr<T>& operator=(const CSmartPtr<T>& obj);//重载赋值操作符
	T* operator->();//重载->操作符
	T& operator*();//重载&操作符
	T* get();
};

//工作指针
class CWorkPtr
{
	template<class T> friend class CSmartPtr;//一大亮点,将类模板声明为友元类
	int UseCnt;//被引用的次数
public:
	CWorkPtr();
	~CWorkPtr();
	void Disp();
};

//实现文件

#include "stdafx.h"
#include "SmartPointer.h"

//智能指针
template<class T>
CSmartPtr<T>::CSmartPtr(T* p){
	m_pointer = p; if (m_pointer != NULL) cout << "构造函数:" << m_pointer->UseCnt << endl;
}
template<class T>
CSmartPtr<T>::CSmartPtr(const CSmartPtr<T>& obj){
	m_pointer = obj.m_pointer; ++m_pointer->UseCnt; cout << "拷贝构造函数:" << m_pointer->UseCnt << endl;
}
template<class T>
CSmartPtr<T>::~CSmartPtr(){
	if (m_pointer != NULL && --m_pointer->UseCnt == 0){
		cout << "析构函数:" << m_pointer->UseCnt << endl;  delete m_pointer;
	}
}
template<class T>
CSmartPtr<T>& CSmartPtr<T>::operator=(const CSmartPtr<T>& obj)//重载赋值操作符
{
	if (this != &obj){//防止自我赋值
		if (m_pointer != NULL && --m_pointer->UseCnt == 0) delete m_pointer;//释放自身所拥有的工作指针
		m_pointer = obj.m_pointer; ++m_pointer->UseCnt; cout << "赋值函数:" << m_pointer->UseCnt << endl;//持有另外对象的工作指针
	}
	return *this;
}
template<class T>
T* CSmartPtr<T>::operator->(){ return m_pointer; }//重载->操作符
template<class T>
T& CSmartPtr<T>::operator*(){ return *m_pointer; }//重载&操作符
template<class T>
T* CSmartPtr<T>::get(){ return m_pointer; }

//工作指针
CWorkPtr::CWorkPtr() : UseCnt(1) { cout << "constructor called !" << endl; }
CWorkPtr::~CWorkPtr(){ cout << "distructor called !" << endl; }
void CWorkPtr::Disp() { cout << "I'am CWorkPtr, imped the main fun. Now I am refed by " << UseCnt << " SmartPtrs. " << endl; }

//测试客户端

void main()
{
	cout << "初次被构造>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
	CSmartPtr<CWorkPtr> pNewPtr = new CWorkPtr();//构造函数
	pNewPtr->Disp();
	cout << "首次被引用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
	CSmartPtr<CWorkPtr> pRef1 = pNewPtr;//拷贝构造函数
	pNewPtr->Disp();
	cout << "再次被引用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
	CSmartPtr<CWorkPtr> pRef2; pRef2 = pRef1;//赋值函数
	pNewPtr->Disp();
}

<think>嗯,我现在需要解决用户关于boost shared_ptr在指定行出现断言失败的问题。首先,用户提供了几个引用信息,其中引用[5]明确指出错误原因是智能指针未初始化,并给出了示例代码。用户的需求是查找代码中`boost/include/boost/smart_ptr/shared_ptr.hpp:734`处的`Assertion 'px != 0' failed`错误的解决方案。 首先,我需要理解这个断言错误的含义。根据boost源码,当调用`operator->`或`operator*`时,会检查内部的指针`px`是否为空。如果`px`为0(即nullptr),就会触发这个断言失败。因此,核心问题是使用了未初始化或已释放的`shared_ptr`。 接下来,结合用户提供的引用,特别是引用[5]中的例子,可以看到错误是因为声明了`viewer1`智能指针但未初始化,直接使用导致错误。正确的做法是初始化时分配对象。因此,解决方案的第一步就是检查所有相关智能指针的初始化情况。 然后,我需要列举可能的触发场景。除了未初始化,还有可能是智能指针被重置为null或指向的对象已被释放。例如,在作用域结束时智能指针自动释放对象,后续再使用该指针就会出错。另外,多线程环境下竞争条件也可能导致问题,但相对少见。 用户的问题中提到了具体的文件路径和行号,但实际错误可能发生在代码的任何地方,关键在于找到哪个指针未初始化就被使用。因此,调试时需要检查堆栈回溯,找到引发错误的调用位置。 解决问题的方法包括:使用调试器(如gdb)捕获core文件,检查调用栈;在代码中添加日志或断言,确保指针在使用前非空;审查所有相关智能指针的生命周期管理,确保正确初始化和所有权管理。同时,注意循环引用可能导致内存无法释放,但这里的问题更可能是空指针而非悬垂指针。 最后,用户可能需要具体的步骤指导,比如如何用gdb调试,或者代码审查的重点。此外,建议用户检查第三方库的使用,如引用中提到的PCL库,确保其兼容性或正确初始化。总结解决方案的核心就是保证使用智能指针前其内部指针不为空。 </think>针对 `boost::shared_ptr` 在 `shared_ptr.hpp:734` 处触发 `Assertion 'px != 0' failed` 错误,以下是根本原因分析和解决方案: ### 错误原因 1. **未初始化智能指针**(最常见) 声明了 `shared_ptr` 对象但未分配有效内存,直接调用成员访问操作符 `->` 或解引用操作符 `*`。 ```cpp boost::shared_ptr<MyClass> ptr; // 未初始化,px = nullptr ptr->method(); // 触发断言崩溃 ``` 2. **意外重置指针** 通过 `reset()` 或赋值将指针置空后错误使用: ```cpp ptr.reset(); // px = nullptr ptr->access(); // 触发断言 ``` 3. **对象提前析构** 其他 `shared_ptr` 实例提前释放对象,导致当前指针悬空: ```cpp auto ptr1 = boost::make_shared<MyClass>(); auto ptr2 = ptr1; ptr1.reset(); // 对象未被释放(ptr2仍持有) ptr2.reset(); // 对象实际析构 if(ptr2) ptr2->use(); // 错误:ptr2非空但px=nullptr ``` 4. **多线程竞争** 未加锁的情况下多线程同时修改 `shared_ptr`(较少见)。 --- ### 解决方案 #### 1. **初始化所有智能指针** ```cpp // 错误声明 boost::shared_ptr<MyClass> ptr; // 正确初始化(任选其一) auto ptr = boost::make_shared<MyClass>(); // 推荐 boost::shared_ptr<MyClass> ptr(new MyClass); // 显式构造 ``` #### 2. **使用前检查有效性** ```cpp if(ptr && ptr.unique()) { // 检查非空且独占所有权 ptr->safe_call(); } ``` #### 3. **调试与排查技巧** - **启用Core Dump分析** 通过GDB回溯崩溃点: ```bash gdb ./your_program core (gdb) backtrace ``` - **添加断言检查** 在关键位置插入验证: ```cpp BOOST_ASSERT_MSG(ptr, "Smart pointer is null at function X"); ``` - **日志追踪** 记录 `shared_ptr` 的构造/析构: ```cpp MyClass() { std::cout << "构造@" << this << std::endl; } ~MyClass() { std::cout << "析构@" << this << std::endl; } ``` #### 4. 第三方库集成注意事项 当使用PCL等库时(如引用[2][4][5]): - **检查工厂函数返回值**:PCL的 `createXxx()` 可能返回空指针 - **验证初始化流程**: ```cpp pcl::Visualizer::Ptr viewer = pcl::createVisualizer("Viewer"); // 确认createVisualizer未返回空 ``` --- ### 关键总结 | **错误类型** | **触发场景示例** | **修复方案** | |-------------------|-------------------------------|----------------------------| | 未初始化指针 | `shared_ptr<T> ptr; ptr->foo()` | 必须显式初始化 | | 空指针解引用 | `ptr.reset(); ptr->bar()` | 使用前添加 `if(ptr)` 检查 | | 对象提前释放 | 多实例竞争释放 | 用 `weak_ptr` 替代跨模块传递 | > 💡 **经验提示**:该断言明确指向 `px == nullptr`(即智能指针内部原始指针为空)。优先检查指针初始化状态和生命周期管理逻辑 [^5][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值