关于程序分配内存空间的简单实例如下
int a = 0; //全局初始化区
char *p1; //全局未初始化区
int main() {
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456//0在常量区,p3在栈上。
static int c =0;//全局(静态)初始化区
p1 = new char[10];
p2 = new char[20];
//分配得来得和字节的区域就在堆区。
strcpy(p1, "123456"); //123456//0放在常量区,编译器可能会将它与p3所指向的/"123456/"优化成一个地方。
}
注意,所有程序中出现的常量,或者作为直接数被编码在二进制指令中,或者存放在常量区。
若直接在栈上分配数组,所使用的数组名实际上为一个常量指针。很显然,在堆栈中分配数组时,数组名本身不是一个变量也不占内存存储空间。
程序运行时和存储时的内存模型如下:
(1)new delete
一般大家都知道sizeof不是函数,而是一个关键字(运算符),而且其返回值在编译时就被确定了。new和delete也是关键字,然而相对于sizeof来说,其机制更为复杂。实际上,无论用于调用new还是malloc,都相当于是向操作系统申请资源,资源管理器返回句柄,并同时做记录,为释放时做准备。也有可能向gcc一样,是额外在前面添加大小信息,在申请释放内存时,会向前偏移几个字节得到该块内存所对应的大小。显然,对于第二种方法,对程序员要求高,一旦访问越界破坏了标记就会出现错误。
new出来的对象一定是放在堆上。new返回值一定是一个指针。
明确一点,new/delete new[]/delete[]一定要配套使用。
原因是,无论如何使用delete,程序都可以自动释放为对象数组或为内置类型数组所分配的内存空间。但是,程序却不知道在对象数组中究竟包含几个对象而所需要调用几个析构函数。
(2)malloc free
new和delete是运算符,而malloc和free则是两个标准库函数。更为显著的特点是,malloc和free和构造函数和析构函数无关。实际上new delete等同于调用构造函数和析构函数在调用malloc和free。
内存泄露是申请内存但是没有释放而造成的。