动态内存开辟
1.动态内存开辟相关试题
题目1:
void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); }
解释:这里在Test函数中,只是将str指针本身传过去了,在Getmemory函数中,对形参p进行修改并不会影响到Test函数中str
变量的值。出了Germemory函数str的值还是NULL,此时srtcpy函数对str这个空指针进行操作就是不合法的操作,导致程序错误。
题目二:
char *GetMemory(void) { char p[] = "hello world"; return p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); }
解释:在Getmemory函数中开辟的空间是在栈区上开辟的,当Getmemory函数运行结束时,p所指向的内存空间就已经还给操作系统了,并且被赋值为了随机值。所以在Test函数中打印str指向的空间时,打印出的应该是一串乱码。
题目三:
void GetMemory(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); }
解释:这段代码不细看是没有什么问题的,在Test函数中的printf函数执行结束之后,str仍然指向堆空间中的内存。在程序结束之前应该主动将其释放。
题目四:
void Test(void) { char *str = (char *) malloc(100); strcpy(str, "hello"); free(str); if(str != NULL) { strcpy(str, "world"); printf(str); } }
解释:在free释放了堆中开辟的空间时,应该及时的将free的参数设置为NULL。这里假如代码的第五行执行完毕之后,将str设置为了空指针,就不会出现后续的错误了。
2.c/c++程序中的内存开辟
内存图如图所示。
栈区向下增长,堆区向上增长。栈区和堆区之间是内存映射段。
c/c++程序内存分配的几个区域:
- 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
- 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。
- 数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
- 代码段:存放函数体(类成员函数和全局函数)的二进制代码。
有了这些知识,就可以理解之前为什么加了static的局部变量可以全局使用了:
局部变量实际上是在内存中的栈区开辟空间的, 栈区上的变量的特点就是出了作用域之后,就被销毁。但是被static修饰的变量是存储在数据段的,会一直持续到程序结束才会被销毁,所以被static修饰的局部变量的生命周期变长了。
3.完结
动态内存开辟的全部内容就到这里啦,若有不足,欢迎评论区指正,下期见!