在写C/C++程序时,一提到内存,大多数人会想到内存泄露。内存泄露是一个令人头疼的问题,尤其在开发大的软件系统时。一个经典的现象是,系统运行了10天、1个月都好好的,忽然有一天宕机了:
OOM(Out Of Memory,内存用光)!于是,痛苦地查找内存泄露根源的过程开始了…本拿主要讨论内存使用问题,包括内存泄露、悬挂指针、内存重复申请、变量的作用范围等,涉及指针、数组、引用等的使用。
6.1数组越界
代码示例
#define ARRAY_SIZE 1024char strArray(ARRAY_SIZE];strArray(ARRAY_SIZE]='0';
现象&结果
数组访问越界,程序运行崩溃。
Bug分析
C或C++中,数组的下标地址范围是从[0-(size-1),下标size已经超出了数组范围。
正确代码
#define ARRAY_SIZE 1024char strArray[ARRAY_SIZE];strArray(ARRAY_SIZE-1] ='0';
6.2数组定义和值初始化形式混淆
代码示例
int *ip = new int(12);for (inti=0;i<12;i++ ){ip[i]=i;}delete [] ip;
现象&结果
产生运行时错误,提示如下的错误信息:
glibc detected *** free() : invraid next size (fast)
Bug分析
int "ip=new int(12)表示new了一个整型变量,值是12, ip指向这个变量。
new返回的指针ip是in类型,不是一个数组指针,赋值的时候,采用数组的方式,造成越界访问内存,并且在结束的时候用deltel删除指针数组,造成程序崩渍。
解决方法是:把小括号改写成中括号。
正确代码
int* ip = new int(12];for (int i= 0; i< 12; i++){ip[i] =i;}delete [] ip;
6.3数组传参时的sizeof
代码示例
void copy(int a[], int b[]) {memepy (b, a, sizeof(a));}
现象&结果
copy函数执行后,内存中的内容与设想不符, 目标数组b中的内容不完整,没有把源数组a中的内容全部复制过来。
Bug分析
memepy函数的原型是void *memepy(void *dest, const void *src, size_tn);,它的功能是从源src所指的内存地址的起始位置开始复制n个字节到目标dest所指的内存地址的起始位置中。上述程序中, copy函数的两个形参悬数组a和数组b,函数体中调用了memcp函数,并且为memepy函数的第三个参数赋值sizeof(a)。程序的本意是期望sizeof(a)返回数组a所占的字节数,通过memcpy函数,把源数组a中的内容全部复制到目标数组b中。但是数组int a0作为copy函数的形参,在copy函数体内将退化成指针,所以, sizeof(a)返回的是指针的字节数,而不是数组a的字节数。因此,数组b中只是部分复制了数组a中的内容。解决办法是:在copy函数中增加一个参数,作为数组复制的字节数。
正确代码
void copr (int a[], int b[], int len) { memspy(a, b, sizeof(int)*1en);}void del (int a[], int len){ memset(a, 0, sizeof(int)* en);}
或者用数组的引用方式传参:
void copy(int a[], int (&b)[]) {memcpy(a, b, sizeof(b));}
编程建议
数组传递参数时,连同数组长度一起传入是一个好方法。或者用std::vector代替数组可以避免不必要的麻烦。使用数组的引用,作为函数的参数,也可以解决上面的问题。
6.4临时对象的生存期
代码示例
class MyString {public:MyString(){s_= (char *)malloc(strlen(str) + 1);strcpy (s_, str);}~MyString() {printf("destory n");}friend MyString operator+(const MyString &lstr, const MrString&rstr){size_t llen = strlen(lstr);size_t rlen = strlen(rstr);char buf[llen + rlen +1];strcpy (buf, Istr);strcat(buf, rstr)return MyString(buf);}operator const char *() const {//当string转换char时调用return_s}private:char* _s;};int main(){Mysting s1("hello"), s2( "wold!");const char*p=s1+s2;printi("%os n", p);return 0;}
现象&结果
程序运行时通常是正常的,但有时会出错,特别是在多线程时,会出现奇特的错误:例如,指针p指向的内容不是期望的内容。
Bug分析
错误出在main函数中的const char*p=s1+s2代码行处。程序会首先生成一个临时对象,用来存储