在C/C++實際工程開發中內存操作,稍不留神就會出現千奇百怪的各種bug,導致整個項目組花很大的時間使用各種工具定位錯誤,解決內存操作問題!
對於用戶使用Android手機,用了你開發的APP,非常鬱悶怎麼就越來越慢的困惑,在本章中我不會講用valgrind工具還是火焰圖等其他工具來定位你的問題的位置。我會重點用C/C++說明以下幾點如何預防?
1、防止數組越界操作,使用柔性數組;
2、內存泄露和多次釋放,使用智能指針;
當然你會說還需要注意使用malloc申請了內存後,應該立即檢查指針值是否爲NULL,防止使用值爲NULL的指針;動態申請操作必須和釋放操作匹配;free指針之後必須立即賦值爲NULL,防止野指針等等。有些是習慣問題,如果你注意到了,這都不是問題!
柔性數組是數組大小待定的數組,通過結構體將成員的結構用malloc ()函數進行內存的動態分配,並且分配的內存應該大於結構的大小,以適應柔性數組的預期大小,防止數組越界的問題。
C語言實現:
#include <stdio.h>
#include <malloc.h>
typedef struct _soft_array
{
int len;
int array[];
}SoftArray;
int main(int argc, char **argv)
{
int i = 0;
SoftArray* sa = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) * 5);
sa->len = 5;
for(i=0; i<sa->len; i++)
{
sa->array[i] = i + 1;
}
for(i=0; i<sa->len; i++)
{
printf("sa->array[%d] = %d\n", i,sa->array[i]);
}
free(sa);
return 0;
}
C++實現:
#include <stdio.h>
#include "Array.h"
int main(int argc, char **argv)
{
Array a1(5);
Array a2(0);
if( a1 != a2 )
{
printf("a1 != a2\n");
}
for(int i=0; i<a1.length(); i++)
{
a1[i] = i + 1;
}
for(int i=0; i<a1.length(); i++)
{
printf("Element %d: %d\n", i, a1[i]);
}
a2 = a1;
if( a1 == a2 )
{
printf("a1 == a2\n");
}
for(int i=0; i<a2.length(); i++)
{
printf("Element %d: %d\n", i, a2[i]);
}
return 0;
}
#ifndef _ARRAY_H_
#define _ARRAY_H_
class Array
{
private:
int mLength;
int* mSpace;
public:
Array(int length);
Array(const Array& obj);//拷貝構造函數
int length();
~Array();//析構函數
int& operator[](int i);
Array& operator= (const Array& obj);
bool operator== (const Array& obj);//操作符重載
bool operator!= (const Array& obj);
};
#endif
#include <stdio.h>
#include "Array.h"
Array::Array(int length)
{
if( length < 0 )
{
length = 0;
}
mLength = length;
mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
}
int Array::length()
{
return mLength;
}
Array::~Array()
{
mLength = -1;
printf("~Array = %08X\n", mSpace);
delete[] mSpace;
}
int& Array::operator[](int i)
{
return mSpace[i];
}
Array& Array::operator= (const Array& obj)
{
delete[] mSpace;
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
return *this;
}
bool Array::operator== (const Array& obj)
{
bool ret = true;
if( mLength == obj.mLength )
{
for(int i=0; i<mLength; i++)
{
if( mSpace[i] != obj.mSpace[i] )
{
ret = false;
break;
}
}
}
else
{
ret = false;
}
return ret;
}
bool Array::operator!= (const Array& obj)
{
return !(*this == obj);
}
不好不好,我需要一個通用的模板啊!好吧,你可以使用類模板來實現:
//柔性數組 類模板
#include <cstdlib>
#include <iostream>
#include "Array.hpp"
using namespace std;
int main(int argc, char *argv[])
{
Array<int> ai(5);
for(int i=0; i<ai.length(); i++)
{
ai[i] = i + 1;
}
for(int i=0; i<ai.length(); i++)
{
cout<<ai[i]<<endl;
}
Array<double> ad(6);
for(int i=0; i<ad.length(); i++)
{
ad[i] = (i + 1) / 10.0;
}
for(int i=0; i<ad.length(); i++)
{
cout<<ad[i]<<endl;
}
return 0;
}
#ifndef _ARRAY_H_
#define _ARRAY_H_
template<typename T>
class Array
{
private:
int mLength;
T* mSpace;
public:
Array(int length);
Array(const Array& obj);//拷貝構造函數
int length();//獲取數組長度
~Array();//析構函數
T& operator[](int i);// 重載數組下標運算符,訪問數組元素
Array& operator= (const Array& obj);//拷貝數組類
bool operator== (const Array& obj);//判斷兩個數組是否相等
bool operator!= (const Array& obj);//判斷兩個數組是否不等
};
#endif
#ifndef _ARRAY_DEF_H_
#define _ARRAY_DEF_H_
#include "Array.h"
template<typename T>
Array<T>::Array(int length)
{
if( length < 0 )
{
length = 0;
}
mLength = length;
mSpace = new T[mLength];
}
template<typename T>
Array<T>::Array(const Array& obj)
{
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
}
template<typename T>
int Array<T>::length()
{
return mLength;
}
template<typename T>
Array<T>::~Array()
{
mLength = -1;
delete[] mSpace;
}
template<typename T>
T& Array<T>::operator[](int i)
{
return mSpace[i];
}
template<typename T>
Array<T>& Array<T>::operator= (const Array<T>& obj)
{
delete[] mSpace;
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
return *this;
}
template<typename T>
bool Array<T>::operator== (const Array<T>& obj)
{
bool ret = true;
if( mLength == obj.mLength )
{
for(int i=0; i<mLength; i++)
{
if( mSpace[i] != obj.mSpace[i] )
{
ret = false;
break;
}
}
}
else
{
ret = false;
}
return ret;
}
template<typename T>
bool Array<T>::operator!= (const Array& obj)
{
return !(*this == obj);
}
#endif
在編寫大型程序的時候,有時我們忘記delete分配的內存,或者多次釋放分配的內存,這樣會造成內存泄露和程序的down機。在程序開發中,預先編寫智能指針類代替原生的指針。出現問題後直接返回錯誤。
通過類模板實現的步驟:
(1)構造函數接管內存的申請;
(2)析構函數確保內存被及時釋放;
(3)重載指針運算符*和->模擬指針的行爲;
(4)重載比較運算符== 和 != 模擬指針的比較。
//功能:智能指針
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include "SmartPointer.hpp"
using namespace std;
class Test
{
public:
int i;
void print()
{
cout<<i<<endl;
}
};
int main(int argc, char *argv[])
{
//構造函數 SmartPointer<int> pi (new int(5));
SmartPointer<int> pi = new int(5);
SmartPointer<Test> pt = new Test();
SmartPointer<int> pj = pi;
cout<<*pi<<endl;
*pi = 6;//使用重載操作符
cout<<*pi<<endl;
pt->i = 7;
pt->print();
//使用重載操作符
if(pi == pj)
{
cout<<"=="<<endl;
}else{
cout<<"!="<<endl;
}
return 0;
}
//智能指針 類定義 頭文件 SmartPoint.h
#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_
//類模板
template<typename T>
class SmartPointer
{
protected:
T* m_pointer;
public:
SmartPointer();//構造函數
SmartPointer(const T* pointer);//拷貝構造函數
~SmartPointer();//析構函數
T* operator->();//操作符重載
T& operator*();
bool operator==(const SmartPointer<T>& operater);
bool operator!=(const SmartPointer<T>& operater);
};
#endif
//智能指針 類成員函數定義 頭文件 SmartPoint.hpp
#ifndef _SMARTPOINTER_DEF_H_
#define _SMARTPOINTER_DEF_H_
#include "SmartPointer.h"
template<typename T>
SmartPointer<T>::SmartPointer()
{
m_pointer = NULL;
}
template<typename T>
SmartPointer<T>::SmartPointer(const T* pointer)
{
m_pointer = const_cast<T*>(pointer);
}
template<typename T>
SmartPointer<T>::~SmartPointer()
{
delete m_pointer;
}
template<typename T>
T* SmartPointer<T>::operator->()
{
return m_pointer;
}
template<typename T>
T& SmartPointer<T>::operator*()
{
return *m_pointer;
}
template<typename T>
bool SmartPointer<T>::operator==(const SmartPointer<T>& operater)
{
return m_pointer == operater.m_pointer;
}
template<typename T>
bool SmartPointer<T>::operator!=(const SmartPointer<T>& operater)
{
return m_pointer != operater.m_pointer;
}
#endif
下載
https://download.csdn.net/download/u010872301/10432433