C++中,进程分为代码段,数据段,堆,内存映射段,栈,内核空间,其中,栈空间大小为8M,堆空间大小为2G(在32位平台下)
栈又叫堆栈,函数调用会建立栈桢,存储局部变量/形参/返回值等等,栈是向下增长的(高地址向低地址使用)。
内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
堆用于程序运行时动态内存分配,堆是向上增长的。
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = {1, 2, 3, 4};
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof (int)*4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
free (ptr1);
free (ptr3);
}
其中关于malloc | free | calloc | realloc的使用规范如下:
静态内存开辟方式:
int a = 0;//4byte
int arr[10] = { 0 };//40byte
通过定义栈上的临时变量,在定义变量时,需要指定变量的大小,但是对于静态内存在编译阶段不适用,有些大小预先不知道,需要代码编译阶段才会知道,因此引入了动态内存
malloc和free
#include<stdlib.h>
void* malloc (size_t size);
int* ptr = (int*)malloc(10 * sizeof(int));
说明:void*:这块内存是为谁申请的也不知道,返回什么类型也不合适,那就返回通用类型。
size:要申请的字节数
在堆区上申请size个字节的空间,并返回堆区上的起始地址。
函数返回值:
若开辟成功,返回一个指向开辟好空间的指针;
若开辟失败,则返回空指针NULL。
因此,malloc的返回值一定一定要做检查!!!
free
与malloc对应的是free,主要功能是对malloc动态开辟的空间进行内存的释放和回收
#include<stdlib.h>
void free(void* ptr);
函数功能:
功能:把ptr所指向的空间还给操作系统
- 若参数ptr指向的空间不是动态开辟的,则free函数的行为是标准未定义的。
- 若参数ptr是NULL空指针,即free(NULL);okay,只不过什么都不干。
陷阱:
#include<stdio.h>
#include<stdlib.h>
int main()
{
//申请空间
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return -1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
//释放ptr指向的这段内存
free(p);
//p = NULL;//是否有必要?
return 0;
}
首先:经过malloc函数申请内存空间后,会将ptr指向内存中开辟的空间,而后操作该部分内容,
其次:free函数的作用是释放申请的空间,但是并不会将ptr的内容置空
最后:由于ptr的值没有置空,指向还是之前的区域,会导致后面出现野指针,对该区域非法访问
一定要ptr == NULL;,让ptr永远也找不到这段空间
calloc
#include<stdlib.h>
void* calloc (size_t num, size_t size);
函数功能:
void*:空类型,为了适应各种指针类型,以便正确解引用
num:要申请的元素个数
size:元素大小
功能:为大小为size的num个元素开辟一块空间,并将每一个字节都初始化为0.
若开辟成功,则返回开辟好空间的起始地址
若开辟失败,则返回空指针NULL
因此,与malloc一样,对于calloc的返回值也一定一定要做检查!!!
对比malloc和calloc:
malloc:只负责在堆区申请空间,并返回起始地址,不会初始化空间
calloc:在堆区申请空间,初始化为0,并返回起始地址
realloc
#include<stdio.h>
void* realloc (void* ptr, size_t size);
ptr:要调整的内存地址
size:调整后的新大小
void*:调整后的内存起始地址
函数既可以进行扩容也可以减少容量,当内存不够大进行扩容时,函数在调整原内存空间大小的同时,还会将原内存中的数据移动到新的空间中去