先看一段代码,非常常见的归并排序;
void _MergeSort(int* a, int* tmp, int begin, int end)
{
if (begin >= end)
return;
int mid = begin + ((end - begin)/2);
_MergeSort(a, tmp, begin, mid);
_MergeSort(a, tmp, mid + 1, end);
int index = 0;
int begin1 = begin, end1 = mid;
int begin2 = mid + 1, end2 = end;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
tmp[index++] = a[begin1++];
else
tmp[index++] = a[begin2++];
}
while (begin1 <= end1)
tmp[index++]= a[begin1++];
while (begin2 <= end2)
tmp[index++] = a[begin2++];
memcpy(a + begin, tmp + begin, sizeof(int)*(end-begin+1));
}
void MetgeSort(int* a, int size)
{
int* tmp = (int*)malloc(size*sizeof(int));
int begin = 0, end = size - 1;
_MergeSort(a, tmp, begin, end);
}
代码问题:
malloc出来的空间未释放
如果在malloc与free之间进行抛异常,那么还是存在内存泄漏问题
1.内存泄漏
内存泄漏:C/C++语言堆上开辟空间时,需要进行手动释放,如果不进行释放,则会造成内存泄漏;
1.1内存泄漏的危害
危害:如果长期运行的程序出现内存泄漏,影响非常大,如操作系统,服务器等,出现内存泄漏会导致响应越来越慢;
1.2如果检测内存泄漏
Linux下的工具:dmalloc,用于检查C/C++内存泄露(leak)的工具,即检查是否存在直到程序运行结束还没有释放的内存,以一个运行库的方式发布
window工具:VLD
1.3内存泄漏的解决方案
1.平时养好良好的代码风格~~~
2.事后进行内存泄漏检测;
3.使用RAII思想的智能指针;
2.智能指针
2.1RAII
RAII:一种利用对象生命周期来控制程序资源;
原理:
1.将资源管理封装到一个类中,开辟空间和释放空间分别调用构造析构函数;
2.对象以声明的方式在栈上创建局部变量,RAII跟随整个局部变量的生命周期,如果变量出了作用域,则会调用析构函数释放资源;
2.2auto_ptr
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_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 _str;
_ptr = ap._ptr;
ap._ptr = NULL:
}
return *this;
}
T& operator*(){ return *_ptr; }
T* operator->{return _ptr; }
private:
T* _ptr;
};
但是传统的智能指针不支持拷贝,因为拷贝之后释放会有段错误
原理参考浅拷贝释放;
2.3shard_ptr
shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。
- shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
- 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
- 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
- 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。
template<class T>
class SharedPtr
{
public:
SharedPtr(SharedPtr<T>* sp,int* spcount)
:_ptr(sp)
, _pCount(spcount)
{}
SharedPtr(const SharedPtr<T>& sp)
{
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*pCount);
}
SharedPtr& opertaor=(const SharedPtr<T>& sp)
{
if (this != &sp)
{
if (--(*_pCount) == 0)
{
delete _ptr;
delete _pCount;
}
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*pCount);
}
return *this;
}
~SharedPtr()
{
if (--(*pCount) == 0)
{
delete _ptr;
delete _pCount;
}
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
private:
T* _ptr;
int* _pCount;
};