赞
踩
目录
一,内存泄露
内存泄露,是指因为疏忽或错误造成程序未能释放那些已不在使用的内存的情况;内存泄露并不是内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误失去了对该段内存的控制,因而造成内存的浪费;
内存泄露的危害,长期运行的程序出现内存泄露,影响很大,如操作系统、后台服务器等,出现内存泄露会导致响应越来越慢,最终卡死;
内存泄露的分类
避免内存泄露方式
二,智能指针
RAII(Resource Acquisition Is Initialization),是一种利用对象生命周期来控制程序资源的申请和释放;在对象构造时获取资源,控制对资源的访问使之在对象生命周期内始终保持有效,最后在对象析构的时候释放资源;借此,实际上把管理资源的责任托管给了一个对象;
智能指针,是使用RAII技术的一种封装指针的类对象,重载了相应的运算符,可像指针一样运算,但会自动回收堆上的内存空间,从而避免内存泄露;
好处:
- 不需要显式地释放资源;
- 对象所需资源在其生命周期内始终有效;
- //RAII技术
- template<class T>
- class SmartPtr
- {
- public:
- SmartPtr(T* ptr = nullptr)
- :_ptr(ptr)
- {}
- ~SmartPtr()
- {
- if (_ptr)
- delete _ptr;
- }
- private:
- T* _ptr;
- };
-
- void Func(int* a, int n)
- {
- int* tmp = (int*)malloc(sizeof(int) * n);
- SmartPtr<int> sp(tmp);
- }
-
- int main()
- {
- try
- {
- int arr[] = { 1,2,3,4,5 };
- Func(arr, 5);
- }
- catch (const exception& e)
- {
- cout << e.what() << endl;
- }
- return 0;
- }
智能指针的原理
上述SmartPtr还不能将其称为智能指针,因为其不具有指针行为;指针还可解引用及访问所指空间,因此AutoPtr模板类中还需有*、->重载,才可以让其像指针一样去使用;
- //智能指针类似指针,当还可自动回收内存
- template<class T>
- class SmartPtr
- {
- public:
- SmartPtr(T* ptr = nullptr)
- :_ptr(ptr)
- {}
- ~SmartPtr()
- {
- if (_ptr)
- delete _ptr;
- }
- T& operator*() { return *_ptr; }
- T* operator->() { return _ptr; }
- private:
- T* _ptr;
- };
-
- struct Date
- {
- int _year;
- int _month;
- int _day;
- };
-
- int main()
- {
- SmartPtr<int> sp1(new int);
- *sp1 = 10;
- cout << *sp1 << endl;
-
- SmartPtr<Date> sp2(new Date);
- (*sp2)._year = 2020; // sp2.operator*()._year;
- sp2->_year = 2021; // sp2.operator->()->_year;
- return 0;
- }
三,C++库中的智能指针
C++库中的智能指针都定义在头文件<memory>中;
auto_ptr
- #include<iostream>
- #include<memory>
- using namespace std;
-
- int main()
- {
- auto_ptr<int> ap1(new int);
- *ap1 = 10;
- auto_ptr<int> ap2(ap1); //拷贝构造后,ap1即销毁
- auto_ptr<int> ap3(new int);
- ap3 = ap2; //赋值后,ap2即销毁
- return 0;
- }
- template<class T>
- class AutoPtr
- {
- public:
- AutoPtr(T* ptr = NULL)
- :_ptr(ptr)
- {}
- ~AutoPtr()
- {
- if (_ptr)
- delete _ptr;
- }
- AutoPtr(AutoPtr<T>& ap)
- :_ptr(ap._ptr)
- {
- ap._ptr = NULL;
- }
- AutoPtr<T>& operator=(AutoPtr<T>& ap)
- {
- if (this != &ap)
- {
- if (_ptr)
- delete _ptr;
- _ptr = ap._ptr;
- ap._ptr = NULL;
- }
- return *this;
- }
- private:
- T* _ptr;
- };
unique _ptr
- //为安全起见,不支持拷贝和赋值
- unique_ptr (const unique_ptr&) = delete;
- unique_ptr& operator= (const unique_ptr&) = delete;
- //支持移动构造
- unique_ptr (unique_ptr&& x) noexcept;
- unique_ptr& operator= (unique_ptr&& x) noexcept;
- int main()
- {
- unique_ptr<int> up1(new int), up2(new int);
- *up1 = 10, *up2 = 20;
-
- up1 = move(up2);
- up1.reset(new int);
-
- auto up3 = unique_ptr<int>(up1.get());
- up3.release();
-
- up1.get_deleter()(up1.get());
- return 0;
- }
- template<class T>
- class UniquePtr
- {
- public:
- UniquePtr(T* ptr = nullptr)
- :_ptr(ptr)
- {}
- ~UniquePtr()
- {
- if (_ptr)
- delete _ptr;
- }
- T& operator*() { return *_ptr };
- T& operator->() { return _ptr };
- private:
- //C++98防拷贝方式,只私有声明不实现
- UniquePtr(UniquePtr<T> const&);
- UniquePtr& operator=(UniquePtr<T> const&);
-
- //C++11防拷贝方式,delete
- UniquePtr(UniquePtr<T> const&) = delete;
- UniquePtr& operator=(UniquePtr<T> const&) = delete;
- private:
- T* _ptr;
- };
shared_ptr
- auto ptr = new int;
- //共享同一块空间,共享所有权
- shared_ptr<int> ptr1(ptr);
- shared_ptr<int> ptr2(ptr1);
- //共享同一块空间,但不共享所有权
- shared_ptr<int> ptr1(ptr);
- shared_ptr<int> ptr2(ptr);
实现原理,通过引用计数的方式来实现多个shared_ptr对象之间共享资源;
- shared_ptr在其内部,给每个资源都维护着一份计数,用来记录该份资源被几个对象共享;
- 在对象被销毁时(析构),说明该资源不使用了,引用计数减1;
- 如引用计数为0,说明是最后一个使用该资源的对象,必须释放该资源;
- 如引用计数不为0,说明还有对象在使用该资源,不可释放,否则成野指针;
- template<class T>
- class SharedPtr
- {
- public:
- SharedPtr(T* ptr=nullptr)
- :_ptr(ptr)
- ,_pRefCount(new int(1))
- ,_pMutex(new mutex)
- {}
- ~SharedPtr()
- {
- Release();
- }
- SharedPtr(const SharedPtr<T>& sp)
- :_ptr(sp._ptr)
- , _pRefCount(sp._pRefCount)
- , _pMutex(sp._pMutex)
- {
- AddRefCount();
- }
- SharedPtr<T>& operator=(const SharedPtr<T>& sp)
- {
- if (_ptr != sp._ptr)
- {
- Release();
- _ptr = sp._ptr;
- _pRefCount(sp._pRefCount);
- _pMutex(sp._pMutex);
- AddRefCount();
- }
- return *this;
- }
- T& operator*() { return *_ptr; }
- T* operator->() { return _ptr; }
- int UseCount() { return *_pRefCount; }
- T* Get() { return _ptr };
-
- void AddRefCount()
- {
- _pMutex->lock();
- ++(*_pRefCount);
- _pMutex->unlock();
- }
- private:
- void Release()
- {
- bool deleteflag = false;
- _pMutex.lock();
- if (--(*_pRefCount == 0))
- {
- delete _ptr;
- delete _pRefCount;
- deleteflag = true;
- }
- if (deleteflag == true)
- delete _pMutex;
- }
- private:
- T* _ptr;
- int* _pRefCount;
- mutex* _pMutex; // 互斥锁
- };
shared_ptr线程安全问题
shared_ptr循环引用
- struct listnode
- {
- ~listnode() { cout << "~listnode()" << endl; }
- int _data;
- shared_ptr<listnode> _prev;
- shared_ptr<listnode> _next;
- };
-
- int main()
- {
- shared_ptr<listnode> node1(new listnode);
- shared_ptr<listnode> node2(new listnode);
- cout << node1.use_count() << endl;
- cout << node2.use_count() << endl;
-
- node1->_next = node2;
- node2->_prev = node1;
- cout << node1.use_count() << endl;
- cout << node2.use_count() << endl;
- return 0;
- }
weak_ptr
- struct listnode
- {
- ~listnode() { cout << "~listnode()" << endl; }
- int _data;
- weak_ptr<listnode> _prev;
- weak_ptr<listnode> _next;
- };
-
- int main()
- {
- shared_ptr<listnode> node1(new listnode);
- shared_ptr<listnode> node2(new listnode);
- cout << node1.use_count() << endl;
- cout << node2.use_count() << endl;
-
- node1->_next = node2;
- node2->_prev = node1;
- cout << node1.use_count() << endl;
- cout << node2.use_count() << endl;
- return 0;
- }
如不是new出来的对象,使用删除器;
- //仿函数删除器
- template<class T>
- struct FreeFunc
- {
- void operator()(T* ptr)
- {
- cout << "free:" << ptr << endl;
- free(ptr);
- }
- };
-
- template<class T>
- struct DeleteArrayFunc
- {
- void operator()(T* ptr)
- {
- cout << "delete[]:" << ptr << endl;
- delete[] ptr;
- }
- };
-
- int main()
- {
- FreeFunc<int> freefunc;
- shared_ptr<int> sp1((int*)malloc(4), freefunc);
-
- DeleteArrayFunc<int> deletearrayfunc;
- shared_ptr<int>sp2((int*)malloc(4), deletearrayfunc);
- }
C++11和boost中智能指针的关系
- C++98中产生了第一个智能指针auto_ptr;
- C++boost给出了更加实用的scoped_ptr、shared_ptr、weak_ptr;
- C++TR1,引入了shared_ptr等,但TR1不是标准版;
- C++11,引入了unique_ptr、shared_ptr、weak_ptr,uniqu_ptr对应boost的scoped_ptr,且这些智能指针的实现原理参考了boost中的实现;
附:RAII扩展
RAII思想除了可以原来设计智能指针,还可以用来设计守卫锁,防止异常安全导致的死锁问题;
- #include<iostream>
- #include<thread>
- #include<mutex>
- using namespace std;
-
- template<class Mutex>
- class LockGuard
- {
- public:
- LockGuard(Mutex& mtx)
- :_mutex(mtx)
- {
- _mutex.lock();
- }
- ~LockGuard()
- {
- _mutex.unlock();
- }
- LockGuard(const LockGuard<Mutex>&) = delete;
- private:
- Mutex& _mutex; //必须使用引用
- };
-
- mutex mtx;
- static int n = 0;
-
- void Func()
- {
- for (size_t i = 0; i < 1000000; ++i)
- {
- LockGuard<mutex> lock(mtx);
- ++n;
- }
- }
-
- int main()
- {
- int begin = clock();
- thread t1(Func);
- thread t2(Func);
-
- t1.join();
- t2.join();
-
- int end = clock();
- cout << n << endl;
- cout << "cost time:" << end - begin << endl;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。