摘要:栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。栈区主要存放运行函数而分配的局部变量函数参数返回数据返回地址等。
我们到现在为止掌握的是什么样的内存开辟方式呢
//创建一个变量int val = 20; //局部变量 在栈空间中开辟4个字节int g_val = 10; //全局变量 在静态区中开辟4个字节//创建一个数组char arr[10] = {0}; //局部区域 在栈空间中开辟10个字节连续的空间char g_arr[5] = {0};//全局区域 在静态区空间中开辟5个字节的连续空间
但是上述的开辟空间的方式有两个特点:
c99是支持变长数组的,但现在很多编译器就不支持c99,连vs都不支持,所以就有动态内存的概念
c语言提供了一个动态内存开辟的函数
void* malloc(size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
1.如果开辟成功,则返回一个指向开辟好空间的指针。
2.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
3.返回值的类型是 void ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。*
4.如果参数 size 为0,malloc的行为是标准未定义的,取决于编译器。
#include #include #include #include int main(){ //向内存申请10个整形的空间 int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { //把开辟失败的信息打印出来 printf("%s",strerror(errno)); } else { //正常使用空间 int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i;//在找下标为i的元素 } for (i = 0; i < 10; i++)//再把每个元素打印出来 { printf("%d ", *(p + i)); } } return 0;}
我们可以用INT_MAX(他是整形最大),一个超级大的数字
free函数用来释放动态开辟的内存。
1.如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
2.如果参数 ptr 是NULL指针,则函数什么事都不做。
malloc和free是成对使用的,谁开辟谁释放
在内存中开辟一个数组,把元素都改成零
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
当然我们可以申请空间,但会不会遇到申请的空间不够了,想要增加一些些,大了想要去掉一些些
1.如果p指向的空间之后有足够的内存空间可以追加,则直接追加,后返回p
2.如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一块新的内存区域,开辟一块满足需求的空间,并且把原来的内存中的数据拷贝回来,释放旧的内存空间,最后返回新开辟的内存空间地址
3.但也有一个大问题,就是开辟INT_MAX,用新的变量ptr来接收realloc返回值
#include #include int main(){ int* p = (int*)malloc(40);//没成功就会有大问题 int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i; } free(p); p = NULL; return 0;}
所以为了防止没有开辟动态内存成功就需要做个判断
#include #include #include #include int main(){ int* p = (int*)malloc(5*sizeof(int)); if (p == NULL)//这里我的确判断有没有开辟成功了 { printf("%s", strerror(errno)); } else { int i = 0; for (i = 0; i < 10; i++)//但是我这里访问10个整型的空间 { *(p + i) = i; } } free(p); p = NULL; return 0;}
int main(){ int a = 0; int* p = &a; *p = 20; free(p); p = NULL; return 0;}
#include #include #include #include int main(){ int* p = (int*)malloc(40); if (p == NULL) { return 0;//如果是空指针就直接返回,不干了 } int i = 0; for (i = 0; i < 10; i++) { *p++ = i;//这个++就是bug的地方 } //回收空间 free(p); p = NULL; return 0;}
只要p不是指向申请的空间的首地址,其他地方都是错的
#include #include #include #include int main(){ int* p = (int*)malloc(40); if (p == NULL) { return 0; } //使用 //释放 free(p); //... free(p); return 0;}
#include #include #include #include int main(){ while (1) { malloc(100); } return 0;}
void GetMemory(char* p){ p = (char*)malloc(100);}void Test(void){ char* str = NULL; GetMemory(str); strcpy(str,"hello world"); printf(str);//这个写法和printf("%s",str);是一样的}int main(){ Test(); return 0;}
问运行Test函数会有什么样的结果
#include #include #include #include void GetMemory(char* *p){ *p = (char*)malloc(100);}void Test(void){ char* str = NULL; GetMemory(&str); strcpy(str,"hello world"); printf(str);//这个写法和printf("%s",str);是一样的 free(str);//用完就释放 str = NULL;}int main(){ Test(); return 0;}
char* GetMemory(void){ char p[] = "hello world"; return p;}void Test(void){ char* str = NULL; str = GetMemory(); printf(str);}int main(){ Test(); return 0;}
请问运行Test 函数会有什么样的结果
输出随机值
既然是p被销毁了,那我们让他不销毁就可以了延长它的生命周期用static
char* GetMemory(void){ static char p[] = "hello world"; return p;}void Test(void){ char* str = NULL; str = GetMemory(); printf(str);}int main(){ Test(); return 0;}
void GetMemory(char **p, int num){*p = (char *)malloc(num);}void Test(void){char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);}
这题基本和第一题一样,不过这题就只有内存泄漏的错误
#include #include void GetMemory(char** p, int num){ *p = (char*)malloc(num);}void Test(void){ char* str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); free(str);//用完就释放,防止内存泄漏 str = NULL;}int main(){ Test(); return 0;}
void Test(void){ char* str = (char*)malloc(100); strcpy(str, "hello"); free(str); if (str != NULL) { strcpy(str, "world"); printf(str); }}
问题非常大的打印出结果
#include #include #include void Test(void){ char* str = (char*)malloc(100); strcpy(str, "hello"); free(str);//这里考查的是free释放后并没有使str为NULL,所以下面if判断就没有作用,如果使他有作用就让str为NULL str = NULL; if (str != NULL) { strcpy(str, "world"); printf(str); }}int main(){ Test(); return 0;}
这道题真正目的就是让你什么都不打印
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/120821.html
摘要:虚拟机在执行程序的过程中会把它所管理的内存划分为若干个不同的数据区域。栈帧栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧的概念结构如下运行时数据区脑图高 这里我们先说句题外话,相信大家在面试中经常被问到介绍Java内存模型,我在面试别人时也会经常问这个问题。但是,往往都会令我比较尴尬,我还话音未落,面试者就会背诵一段(Java虚拟...
摘要:请求的多阶段异步处理多阶段异步处理请求与事件驱动架构是密切相关的,也就是说,请求的多阶段异步处理只能基于事件驱动架构实现。 前言 最近在读 Nginx 相关的书籍,做一下读书笔记。 Nginx 作为业界知名的高性能服务器,被广泛的应用。它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程与多工作进程设计、内存池的设计,以下内...
摘要:请求的多阶段异步处理多阶段异步处理请求与事件驱动架构是密切相关的,也就是说,请求的多阶段异步处理只能基于事件驱动架构实现。 前言 最近在读 Nginx 相关的书籍,做一下读书笔记。 Nginx 作为业界知名的高性能服务器,被广泛的应用。它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程与多工作进程设计、内存池的设计,以下内...
摘要:调用函数时,它将用户释放的内存块连接到空闲链上。这个联合体共占用字节。是数字,且顺序递增位置固定,如访问是的元素,即,就直接访问数组的第个位置即可即,这样就不需要前面的索引数组。 baiyan 全部视频:https://segmentfault.com/a/11... 原视频地址:http://replay.xesv5.com/ll/24... 本笔记中部分图片截自视频中的片段,图片版...
摘要:腾讯特约作者姚潮生首先以一个内存泄露实例来开始本节基础概念的内容。堆内存用于存放所有由创建的对象内容包括该对象其中的所有成员变量和数组。回到我们的问题,为什么内存会泄露堆内存中的长生命周期的对象持有短生命周期对象的强软引用,尽管 腾讯Bugly特约作者: 姚潮生 首先以一个内存泄露实例来开始本节基础概念的内容。 实例1:单例导致内存对象无法释放而泄露 showImg(http://i....
阅读 3061·2021-11-24 10:34
阅读 3321·2021-11-22 13:53
阅读 2629·2021-11-22 12:03
阅读 3596·2021-09-26 09:47
阅读 3005·2021-09-23 11:21
阅读 4771·2021-09-22 15:08
阅读 3287·2021-07-23 10:59
阅读 1257·2019-08-29 18:31