网站建设公司骗人,做普通网站选择什么服务器,淮北电子商务网站建设,网站做的比较好的公司动态内存管理 后篇#x1fac5;经典例题#x1f926;♂️题目1#x1f926;♂️题目2#x1f926;♂️题目3#x1f926;♂️题目4#x1fac5;C/C程序的内存开辟前面的一篇文章动态内存管理 前篇#xff0c;我们已经了解过了动态内存管理的相关信息#xff0c…
动态内存管理 后篇经典例题♂️题目1♂️题目2♂️题目3♂️题目4C/C程序的内存开辟前面的一篇文章动态内存管理 前篇我们已经了解过了动态内存管理的相关信息接下来让我们来一起来踩“坑”。当然今天的踩坑是为了面试不踩坑哦 经典例题
♂️题目1
void GetMemory(char* p)
{p (char*)malloc(100);
}void Test(void)
{char* str NULL;GetMemory(str);strcpy(str, hello world);printf(str);
}int main()
{Test();return 0;
}我们来找一找上面的代码有什么问题 好了不绕弯子了来看看到底错了哪些地方
GetMemory(str)中是传值而不是传址。当出了GetMemory函数p指向的地址发生了变化但str依旧是NULL然后就进入了strcpy函数这样就形成了非法访问内存NULL是操作系统的我们用户没有权限访问在GetMemory函数内部动态申请了内存直到程序结束也没有释放内存这样会导致内存泄漏 printfstr这样写也能行为什么吗 我们来看看下面的代码
#includestdio.hint main()
{char ptr[] hehehe;char* p hehehe;printf(%s\n, ptr);printf(%s\n, p);printf(hehehe);return 0;
}//运行结果
*****
hehehe
hehehe
hehehe
*****纳尼这是为什么呢 在解释这个问题前我们先想一下printf的第一个参数是什么答案是必须是指针。那就意味printf(“hehehe”)里面的“hehehe”不是我们所看到的那样而是一个地址。那么它是谁的地址下面的代码会给我们答案
#includestdio.hint main()
{char* p hehehe;printf(%p\n, hehehe);printf(%p\n, p);return 0;
}//运行结果
*****
00AF7B54
00AF7B54*****奥那我就明白了ptr指针指向的是字符串的第一个字符那么运行结果告诉我们printf(“hehehe”)里面传的就是第一个字符的地址。
修改
//修改后
// #includestdio.h
#includestdlib.hvoid GetMemory(char** p) //二级指针接收
{*p (char*)malloc(100); //解引用就是一级指针
}void Test(void)
{char* str NULL;GetMemory(str); //传址strcpy(str, hello world);printf(str);//释放空间free(str);str NULL;}int main()
{Test();return 0;
}♂️题目2
#includestdio.h
#includestdlib.hchar* GetMemory(void)
{char p[] hello world;return p;
}void Test(void)
{char* str NULL;str GetMemory();printf(str);
}int main()
{Test();return 0;
}这个除了没有释放空间就没有其他的问题了吧。 但真相是这样吗 让我们看看运行结果是什么吧 嗯没释放空间也不会导致这种结果吧… 让我们来全面的分析一下吧
关于函数返回信息的问题这一类问题也叫作“返回栈空间地址的问题”函数返回地址地址信息存在但函数内部的栈空间就还给操作系统了操作系统可以把此空间作为别的变量的地址函数动态申请空间直到程序结束也没有释放掉空间会导致内存泄漏
返回栈空间地址的问题这是什么啊 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等 那我们就明白了为什么叫做返回栈空间地址那问题呢 当函数调用结束出了函数在函数里面的空间就会返还给操作系统我们用户没有操作权限。操作系统会把这个空间重新分配给其他变量这样我们就不得而知了
修改
#includestdio.h
#includestdlib.hchar* GetMemory(void)
{char* p hello world; //将第一个字符的地址传给p//static char p[]hello world; //被static修饰的变量存放在数据段静态区//数据段的特点是在上面创建的变量直到程序结束才销毁return p;
}void Test(void)
{char* str NULL;str GetMemory();printf(str);//释放free(str);str NULL;
}int main()
{Test();return 0;
}♂️题目3
#includestdio.h
#includestdlib.hvoid GetMemory(char** p, int num)
{*p (char*)malloc(num);
}void Test(void)
{char* str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str);
}int main()
{Test();return 0;
}这个就很简单了没有释放空间 修改
#includestdio.h
#includestdlib.hvoid 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;
}♂️题目4
#includestdio.h
#includestdlib.hvoid Test(void)
{char* str (char*)malloc(100);strcpy(str, hello);free(str);if (str ! NULL){strcpy(str, world);printf(str);}
}int main()
{Test();return 0;
}这个问题是啥感觉没问题啊不会是str没有置空吧 哈哈其实这个问题很隐蔽不注意看是看不出来的 free的动作是将该内存块返还给操作系统我们没有操作权限故str是野指针造成了非法访问内存 修改
#includestdio.h
#includestdlib.hvoid Test(void)
{char* str (char*)malloc(100);strcpy(str, hello);free(str);str NULL; //在这里置空也是为了符合下面判断的逻辑//那么也不会进入if里面造成非法访问if (str ! NULL){strcpy(str, world); printf(str);}
}int main()
{Test();return 0;
}C/C程序的内存开辟 在在这里终于把C语言中的动态内存管理的知识讲解完了。想必大家大概的框架是有的但是对一些专业术语跟底层逻辑不是很清楚。比如什么是堆区什么又是栈区内存中的每一个区域的作用是什么等等 C/C程序内存分配的几个区域
栈区stack在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是 分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等。堆区heap一般由程序员分配释放 若程序员不释放程序结束时可能由OS回收 。分 配方式类似于链表。数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。代码段存放函数体类成员函数和全局函数的二进制代码。字符串常量就在其中
实际上普通的局部变量是在栈区分配空间的栈区的特点是在上面创建的变量出了作用域就销毁。 但是被static修饰的变量存放在数据段静态区数据段的特点是在上面创建的变量直到程序 结束才销毁。所以生命周期变长。 码文不易各位看官一键三连哦 各位的鼓励与支持是我前进最大的动力