内存分配方式:
1.从静态存储区分配,内存在程序编译的时候就已经分配好了(即已经编址),这些内存在程序的整个运行期间都存在,如全局变量,static变量等。
2.在堆栈上分配,在函数执行期间,函数内部变量(包括形参)的存储单元都创建在堆栈上,函数结束这些存储单元自动释放,堆栈清退。堆栈内存分配运算内置于处理器的指令集中,效率很高,并且一般不存在失败的危险,但是分配的内存容量有限,可能出现堆栈溢出。
3.从堆(heap)或自由存储空间上分配,即动态内存分配,程序在运行期间,用malloc()或者new申请任意数量的内存,程序员自己掌握释放内存的恰当时机(使用free()或delete),动态内存的生存期由程序员决定,使用灵活、
常见的内存错误:
1.内存尚未分配成功,却使用了。 检查指针是否为空
2.内存分配成功,但是尚未初始化就使用它 任何的分配需要初始化
3.内存分配成功已经初始化,但是访问越过了内存的边界。 如数据的越界访问
4.忘记释放内存或者只是释放了一部分的内存,导致内存泄露。 malloc() free() new delete 使用必须配对
5.释放了内存却还在使用。 注意将已经释放的内存设置为NULL,防止产生野指针。 多次释放同一块内存出现错误。 double free
几点规则:
1.用malloc()或者new申请内存之后,应该立即检查指针值是否为NULL或者进行异常处理,以防止使用值为NULL的指针。
2.不要忘记初始化指针,数组和动态内存,防止将未初始化的内存作为右值使用。
3.避免数组下标访问越界。
4.动态内存的分配和释放必须配对,防止内存泄露。
5.释放内存后应该立即把指针设置成NULL,防止野指针。
指针参数如何传递内存:
1.指针作为参数进行内存的分配,传递指针的指针,或者传递指针的引用。因为实参是拷贝一份传递给形参。
void getmemory(char** p,int num)
{
*p=(char*)malloc(sizeof(char)*num);
}
void getmemory(char*& p,int num)
{
p=new char;
}
2.用函数返回值传递来申请内存
char* getmemory(int num)
{
char* p=NULL;
p=(char*)malloc(num*sizeof(char));
return p;
}
3.注意不可以返回局部变量的地址
char* getmemory(int num)
{
char* p="hello world";
return p;
}
char* getmemory()
{
char p[]="hello world";
return p;
}
第一种 返回常量存储区的地址OK 第二种错误!!
内存释放:
#include <iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int main()
{
int* p=new int(5);
if(p==NULL) throw 1;
cout<<p<<endl;
delete p;
cout<<p<<endl;
return 0;
}
指针被释放后其指向的地址内人不变,(不等于NULL),但是该地址对应的内存是垃圾------>p成了一个野指针。 所以必须进行设置成NULL
经典:指针消亡了,并不代表它所指的内存会被自动释放 AND 内存被释放了,并不表示指针会消亡或者成了NULL。
野指针:
1.未初始化指针变量,任何指针在初始化时不会自动成为NULL指针,它会乱指一气,所以指针变量创建的同时应该初始化,或者设置成NULL。
2,.指针p被释放后,未设置为NULL。
3.指针变量超越了变量的作用范围。
class A{
public:
void func(void){cout<<"A::func"<<endl;}
~A(){cout<<"~A()"<<endl;}
};
int main()
{
A* p=NULL;
{
A a;
p=&a;//注意a的生命期
}
p->func();//p是野指针
return 0;
}
上述代码: 根本原因是a虽然退栈,但是仅仅是调用了析构函数,并没有清除a的内存(a的内存仍然在函数堆栈上),所以结果没有错。
MALLOC FREE AND NEW DELETE
maloc,free为C语言的库函数,而不是运算符。 new delete是运算符而不是库函数
用malloc,free函数进行对象的动态内存管理,不能调用构造函数和析构函数。必须程序员自己写函数来完成初始化和清除的工作。
new.delete会自动的调用构造和析构函数来进行调用。
某些情况下,malloc/free效率更高。用户可以自定义类重载 new/delete实现个性的内存分配和释放策略。
注意:如果使用free()来释放new创建的对象,那么该对象可能会无法执行析构函数而导致程序出错, C++并不保证new的底层会用malloc(),而且在一些实现中,malloc和new使用不同的堆,同样,用delete释放malloc申请的动态内存,理论是程序不会出错,但是该程序的可读性会很差。
p==NULL free多次都没事,但是p!=NULL,多次释放会出现错误