内存分配经典试题及柔性数组

相关标签: # 数据
#define _CRT_SECURE_NO_WARNINGS 1
#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);
//}
//int main()
//{
// Test();
// return 0;
//}
//1.运行代码程序会出现崩溃的现象
//2.程序存在内存泄漏的问题
//
//str以值传递的形式给p,p是GetMemory函数的形参,只能在函数内部有效,等GetMemory函数返回
//之后,动态开辟内存尚未释放并且无法找到,所以会造成内存泄漏
//
//方法一改正后:
//void 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;
//}
//方法二改正后:
//char* GetMemory(char* p)
//{
// p = (char*)malloc(100);
// return p;
//}
//void Test(void)
//{
// char* str = NULL;
// str=GetMemory(str);
// strcpy(str, "hello world");
// printf(str);
// free(str);
// str = NULL;
//}
//int main()
//{
// Test();
// return 0;
//}
//请问结果如何
//char* GetMeory(void)
//{
// char p[] = "hello world";
// return p;
//}
//void Test(void)
//{
// char* str = NULL;
// str = GetMemory();
// printf(str);
//}
//int main()
//{
// Test();
// return 0;
//}
//输出随机值,存在非法访问内存问题
//p数组的地址的确返会给str,但是p数组是在函数内部有效,出了函数就无效了
//返回栈空间的地址的问题
//
//如下:
//int* test()
//{
// int a = 10;//栈区
// return &a;
//}
//int main()
//{
// int* p = test();
// *p = 20;//err
// return 0;
//}
//上面是问题代码
//
//int* test()
//{
// static int a = 10;//静态区
// return &a;
//}
//int main()
//{
// int* p = test();
// *p = 20;
// return 0;
//}
//上面代码没问题
//
//int* test()
//{
// int*ptr = malloc(100);//堆区,malloc开辟的空间不free依然存在
// return ptr;
//}
//int main()
//{
// int* p = test();//把malloc开辟的空间地址给了p,然后ptr的地址出函数销毁
// 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);
// //没有释放动态开辟的内存,导致内存泄漏了
// //改正后
// //free(str);
// //str = NULL;
//}
//int main()
//{
// Test();
// return 0;
//}
//能输出hello,但是内存泄漏
//下面代码结果如何
//void Test(void)
//{
// char* str = (char*)malloc(100);
// strcpy(str, "hello");
// free(str);
// //改正后:
// //str = NULL;
// if (str != NULL)
// {
// strcpy(str, "world");
// printf(str);
// }
//}
//int main()
//{
// Test();
// return 0;
//}
//非法访问内存,篡改动态内存区的内容,后果难以预料,非常危险
//因为free释放str指向的空间后,并不会把str置为NULL,str成为野指针,if(str!=NULL)语句不起作用
////C/C++程序内存分配的几个区域
//1.栈区(stack):在执行函数时,函数内局部变量的储存单元都可以在栈上创建,函数执行结束时这些储存单元自动被释放。
// 栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
// 栈区主要存放运行函数而分配的局部变量,函数参数,返回数据,返回地址等。
//2.堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。
//3.数据段(静态区)(static):存放全局变量、静态数据。程序结束后由系统释放。
//4.代码段:存放函数体(类成员函数和全局函数)的二进制代码。
////////柔性数组
//C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做【柔性数组】成员。
//柔性数组的特点:
// ·结构中的柔性数组成员面前必须至少一个其他成员。
// ·sizeof返回的这种结构大小不包括柔性数组的内存。
// ·包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于
// 结构的大小,以适应柔性数组的预期大小。
//struct S
//{
// int a;
// //未知大小的-柔性数组成员-数组的大小是可以调整的
// int arr[];//==int arr[0];
//};
//
//方法1:柔性数组
//struct S
//{
// int a;
// int arr[];
//};
//int main()
//{
// struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));
// ps->a = 100;
// int i = 0;
// for (i = 0; i < 5; i++)
// {
// ps->arr[i] = i;
// printf("%d ", ps->arr[i]);
// }
// printf("\n");
// struct S* ptr = realloc(ps, 44);
// if (ptr != NULL)
// {
// ps = ptr;
// for (i = 5; i < 10; i++)
// {
// ps->arr[i] = i;
// printf("%d ", ps->arr[i]);
// }
// }
// free(ps);
// ps = NULL;
// return 0;
//}
//
//方法2:使用函数也能实现柔性数组
//struct S
//{
// int a;
// int* arr;
//};
//int main()
//{
// struct S* ps = (struct S*)malloc(sizeof(struct S));
// ps->arr = malloc(5 * sizeof(int));//两次malloc开辟的空间不是连续的
// int i = 0;
// for (i = 0; i < 5; i++)
// {
// ps->arr[i] = i;
// printf("%d ", ps->arr[i]);
// }
// int* ptr = realloc(ps->arr, 10 * sizeof(int));
// if (ptr != NULL)
// {
// ps->arr = ptr;
// }
// for (i = 5; i < 10; i++)
// {
// ps->arr[i] = i;
// printf("%d ", ps->arr[i]);
// }
// free(ps->arr); //释放要有先后顺序
// ps->arr = NULL;
// free(ps);
// ps = NULL;
// return 0;
//}
//
//上述代码1和代码2可以完成同样的功能,但是方法1的实现有两个好处:
//第一个好处:方便内存释放
// 如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,
// 但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要
// 的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉
//第二个好处:这样有利于访问速度
// 连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)
//
文章来源: https://blog.51cto.com/u_15712753/5668193
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报