目录
一、为什么要有动态内存分配
(1)我们已经掌握的内存方式的特点
(2)需求
二、malloc和free
2.1.malloc
2.1.1函数原型
2.1.2函数使用
2.1.3应用示例编辑
2.2free
2.2.1函数原型
2.2.2函数使用
三、calloc和realloc
3.1.calloc
3.1.1函数原型
3.1.2函数使用
3.1.3应用举例编辑
3.2realloc
3.2.1函数原型
3.2.2函数使用
四、常⻅的动态内存的错误
对NULL指针的解引⽤操作
对动态开辟空间的越界访问
对⾮动态开辟内存使⽤free释放
使⽤free释放⼀块动态开辟内存的⼀部分
对同⼀块动态内存多次释放
动态开辟内存忘记释放(内存泄漏)
五、动态内存经典笔试题分析
test1
解析
test2
解析
test3
解析
test4
解析
六、柔性数组
6.1概念
6.2特点
6.3优势
七、总结C/C++中程序内存区域划分
//已经掌握的内存分配方式
int a = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
void* malloc (size_t size);
void free (void* ptr);
void* calloc (size_t num, size_t size);
void* realloc (void* ptr, size_t size);
void test()
{
int *p = (int *)malloc(INT_MAX/4);
*p = 20;//如果p的值是NULL,就会有问题
free(p);
}
void test()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
}
void test()
{
int a = 10;
int *p = &a;
free(p);//ok?
}
void test()
{
int *p = (int *)malloc(100);
p++;
free(p);//p不再指向动态内存的起始位置
}
void test()
{
int *p = (int *)malloc(100);
free(p);
free(p);//重复释放
}
void test()
{
int* p = (int*)malloc(100);
if (NULL != p)
{
*p = 20;
}
}
int main()
{
test();
while (1);
}
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
1.GetMemory函数采用值传递的方式,无法将malloc开辟空间的地址,返回放在str中 ,调用结束后str依旧是NULL指针。2.strcpy中使用了str,就是对NULL指针接引用操作,程序崩溃。3.没有free,后续无法销毁,内存泄漏
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(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);
}
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
if(str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
C99 中,结构中的最后⼀个元素允许是未知⼤⼩的数组,这就叫做『柔性数组』成员。
struct st_type
{
int i;
int a[0];//或者可以写成int a[];
//柔性数组成员
}