存储区划分
内存管理:软件运行时对计算机内存资源的分配和使用的技术,其最主要的目的是高效、快速的分配、并在适当的时候释放和回收资源
内存分配方式
- 从静态存储区域分配:内存在程序编译时已经分配好,这块内存在程序的整个运行期间都存在。例如:全局变量、static变量
- 在栈上创建,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,,函数执行结束后这些存储单元你自动被释放。栈内存分配运算内置于处理器的指令中,效率高,但能够分配的内存容量有限
- 从堆上分配(动态内存分配),程序运行时用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存,动态内存的生存周期由程序员决定,使用灵活,但有许多缺点
静态内存分配(BSS段、数据段)
BSS段(Block Started by Symbol):
用来存放程序中未初始化的全局变量和静态变量,它不包含任何数据,只是简单地维护开始和结束的地址,即总大小,以便内存区能在运行时分配并有效地清零。BSS不占用磁盘空间,只在运行时占用。
数据段(data segment)
用来存放已初始化的全局变量和静态变量的一块内存区域,可以分为只读数据段和读写数据段,字符串常量等,但一般都放在只读数据段中
栈内存
用来存放程序临时创建的局部变量
栈内存的错误使用
char *fun()
{
//注意此处是把常量区的字符串“iphone”拷贝到栈内存中。
char string[] = "iphone";
return string; //栈内存返回是不安全的,禁⽌!!!
}
常量区
//'a' 字符常量
//5 整形常量
//"iPhone" 字符串常量
//常量占⽤内存,只读状态,决不可修改!
char * string = "iPhone";
string[0] = 'a'; //运⾏崩溃!
静态存储区
- 只初始化一次
- 如果初始没给值,默认值为0
- 只有程序退出才释放
- 将变量定义的类型前加static,则该变量存储存储在静态存储区
堆区
malloc等内存分配函数分配的内存,手动分配,手动释放
代码区
用于存放程序执行代码的一段区域,所有的语句编译后会生成CPU指令存储在代码区
堆内存分配函数
动态内存分配
void * malloc(unsigned size);//从内存的堆区分配大小为size个字节的连续内存空间
//如果内存分配成功,返回内存的首地址;失败则返回NULL
//从内存中申请一块空间,可以存储4个int类型的数据即共16个字节
//赋值要求=两边的类型要一致,所以要进行一个强制转换,由默认的void * 转换为int *
int *p = (int *) malloc(4*sizeof(int)); //16个字节
//使用一个函数给malloc申请的空间进行初始化
memset(p, 'A', 16);//中间的参数读的是ASCII码值,所以写0还是会出现奇怪的数,因此最好直接写一个字符
if (p != NULL) {
//申请成功要做的事
//p中存放的是新申请的内存空间的首地址
*p = 10;
*(p+1) = 100;
*(p+2) = 1000;
*(p+3) = 10000;//存放4个整数
//如果分配的空间未赋值,那么初始值会是垃圾数,不一定为0
}else{
printf("内存申请失败!\n");
}
for (int i = 0; i < 4; i++) {
printf("%c\t",*(p+i));//循环结束后,p就不再指向刚才的首地址,而是指向其他未知空间,此时,就不要用p再进行其他操作了
}
内存释放
void free(void *)//free函数的作用是释放内存,内存释放是标记删除
其他内存分配函数
calloc
分配n个size大小的空间,并且把该内存上的所有字节清零
void * calloc(unsigned n,unsigned size);
//calloc函数
//格式:calloc(块数,长度)即分配块数个长度的内存空间
//可以自动初始化为0,不需要memset了
int *p = (int *)calloc(4,sizeof(int));
if (p != NULL) {
//申请成功要做的事
//p中存放的是新申请的内存空间的首地址
*p = 10;
*(p+1) = 100;
*(p+2) = 1000;
*(p+3) = 10000;//存放4个整数
//如果分配的空间未赋值,那么初始值会是垃圾数,不一定为0
}else{
printf("内存申请失败!\n");
}
for (int i = 0; i < 4; i++) {
printf("%d\t",*(p+i));//循环结束后,p就不再指向刚才的首地址,而是指向其他未知空间,此时,就不要用p再进行其他操作了
}
realloc
按给定的地址以及给定的大小重新分配
void *realloc(void *p,unsigned newSize);
//realloc函数:按给定的地址以及给定的大小给已经存在的空间进行扩展
//格式:realloc(地址,新长度)
int *p = (int *)calloc(4,sizeof(int));
p = (int *)realloc(p,40*sizeof(int));//为了分配连续的空间,若当前空间不够,则会找新的足够大的空间,返回新的地址
if (p != NULL) {
//申请成功要做的事
//p中存放的是新申请的内存空间的首地址
*p = 10;
*(p+1) = 100;
*(p+2) = 1000;
*(p+3) = 10000;//存放4个整数
//如果分配的空间未赋值,那么初始值会是垃圾数,不一定为0
}else{
printf("内存申请失败!\n");
}
for (int i = 0; i < 40; i++) {
printf("%d\t",*(p+i));//循环结束后,p就不再指向刚才的首地址,而是指向其他未知空间,此时,就不要用p再进行其他操作了
}
内存操作函数
初始化内存
void *memset(void *s , int c , size_t n) ;//从s指向的内存开始初始化n个字节的内容为c
内存拷贝
void *memcpy(void *dest,const void*source , size_t n) ;//从source指向的内存开始拷⻉到dest,拷⻉n个字节
内存比较
int memcmp(const void *buf1, const void *buf2, unsigned int count)
//⽐较buf1和buf2指向的内存是否相同,⽐较count个字节