我们知道内存的使用方式,可以在栈区,静态区,堆区,申请空间来储存变量。

但是他们这些内存区所存储的东西是不一样的。

局部变量

函数的形式参数

栈区

动态内存分配申请的空间

malloc,calloc,realloc,

堆区

全局变量,

静态变量,

static修饰的变量

静态区

创建一个变量:

int a=10;int arr[]={0};——局部变量——栈区;

int a=10;int arr[]={0};——全局变量——静态区;

但是面两种申请的空间都是固定的,例如我们在使用数组的时候,有时候发现数组的申请的空间小了,又回去改数组的大小,改了之后又发现用不完,就回给我们的空间造成浪费,数组而不能达到随心所欲的修改申请给我们带来不便。这就是我们今天学习的动态内存分布就可以很好的解决相这个问题,当我们的申请的空间小了,我们可以直接扩充,用不完的可以直接减少。

1.malloc

头文件: #include<stdlib.h>

函数框架:void*malloc(size_t size)。

返回值:函数的返回类型位空指针类型,可根据具体的申请的和需要强行转换指针类型,返回的指针指向申请的空间的是首地址。

参数:函数的参数是一个无符号整型数字(size_t  size),代表申请空间的大小,单位为字节。

如果申请成功函数返回申请在堆区空间的地址,如果申请不成功,就会返回NULL(空指针)。

实例:

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)malloc(sizeof(int) * 10);//申请了一个可以存放10个int类型的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");}else{printf("申请成功\n");}return 0;
}

这里申请成功了

让我们看一下申请不成功的情况

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)malloc(100000000000000000*10000000000000000000);//申请了一个非常大的空间,//已经超出我们堆区的最大存储空间,//肯定会申请失败;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");}else{printf("申请成功\n");}return 0;
}

接下来我们看一下malloc申请空间的使用:

看代码:

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)malloc(sizeof(int)*10);//申请可以存放10个int型变量的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");return 0;//如果申请失败,我们程序就直接退出,因为申请失败也没有必要进行操作;}else{int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;//申请的10个空间,赋值0——9;}for (i = 0; i < 10; i++){printf("%d ", *(p+i));//证明我们我们的数字已经存进去,打印出我们存进去的数字。}}free(p);//当我们的动态申请的空间不再使用的时候,就应该还给操作系统,所以就是用free,对申请的空间释放。p = NULL;//但是我们申请的空间是还给操作系统了,但是指针 p 仍旧可以找到那块空间,所以我们把 p赋值成空指针,将指针 p 与空间完全断开联系。return 0;
}

关于free:

malloc与free,是成对使用的。

2.calloc

头文件:#include<stdlib.h>

函数框架:void*calloc(size_t num,size_t size);

calloc的功能与malloc基本一样,也是从堆区申请一块空间,但是区别就在于calloc会在返回地址之前把申请的空间全部赋值为0;

参数:size_t num——无符号整形数,代表申请空间的个数,size_t size——无符号整形数,代表

申请每个空间的大小,单位为字节。

返回值:函数的返回类型位空指针类型,可根据具体的申请的和需要强行转换指针类型,返回的指针指向申请的空间的是首地址。

如果申请成功函数返回申请在堆区空间的地址,如果申请不成功,就会返回NULL(空指针)。

实例2.

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)calloc(10,sizeof(int));//申请可以存放10个int型变量的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");return 0;//如果申请失败,我们程序就直接退出,因为申请失败也没有必要进行操作;}else//申请成功开始使用{int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));//查看在为赋值的时候申请的空间里面存储是不是0;*(p + i) = i;//申请的10个空间,赋值0——9;}printf("\n");for (i = 0; i < 10; i++){printf("%d ", *(p + i));//证明我们的数字已经存进去,打印出我们存进去的数字。}}free(p);p = NULL;//用完别忘记释放哦。return 0;
}

3.realloc

realloc函数使我们动态内存管理更加灵活。

有时会发现过去申请的空间太小了,有时候我又会觉得申请的空间太大了,那为了合理的内存,我们呢一定会对内存进行灵活的调整,realloc就可以做到对内存大小的调整。

函数原型:void* realloc(void*ptr,size_t size)

参数:void*ptr ,ptr为要调整的空间的地址,size_t size为调整之后的新大小。

返回值:调整之后的内存的起始位置,

函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间里面去。

realloc使用实例:

#include<stdio.h>
#include<stdlib.h>
int main()
{int* p = (int*)calloc(10, sizeof(int));//申请可以存放10个int型变量的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");return 0;//如果申请失败,我们程序就直接退出,因为申请失败也没有必要进行操作;}else//申请成功开始使用{int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));//查看在为赋值的时候申请的空间里面存储是不是0;*(p + i) = i;//申请的10个空间,赋值0——9;}printf("\n");for (i = 0; i < 10; i++){printf("%d ", *(p + i));//证明我们的数字已经存进去,打印出我们存进去的数字。}}printf("\n");//这时我们发现内存不够int* p1 = (int*)realloc(p, sizeof(int) * 15);//我们将申请空间扩大到可以存放15个int型数字。if (p1 == NULL){printf("申请失败");return 0;}for (int i = 10; i < 15; i++){*(p1 + i) = i;//将新申请的空间赋值10——14;}for (int i = 0; i < 15; i++){printf("%d ", *(p1 + i));}free(p1);p1 = NULL;return 0;
}

关于realloc的注意:

如果原空间之后有足够的空间就可以直接追加,然后返回调整之后的空间的起始位置地址;

如果原空间后面没有足够的空间可以用来追加,则realloc就会重新找一个新的内存区域,将元数据拷贝过去再追加,最后返回新空间的起始位置地址;

要用一个新的指针变量来接受realloc函数的返回值;

关于realloc在内存追加空间的时候,后面没有足够的大小用来追加会重新找一个新的内存区域,将元数据拷贝过去再追加,最后返回新空间的起始位置地址;

实例:

#include<stdio.h>
#include<stdlib.h>
int main()//(1)后面有足够的空间追加;
{int* p = (int*)malloc(1);//申请可以存放1个字节的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");return 0;//如果申请失败,我们程序就直接退出,因为申请失败也没有必要进行操作;}printf("%p\n", p);int* p= (int *)realloc(p, 2);//追加一个字节,后共2个字节;printf("%p\n", p);free(p);p=NULL;return 0;
}

#include<stdio.h>
#include<stdlib.h>
int main()//(1)后面没有足够的空间追加;
{int* p = (int*)malloc(1);//申请可以存放1个字节的空间;if (p == NULL)//判断是否申请失败,申请失败会返回空指针(NULL).{printf("申请失败\n");return 0;//如果申请失败,我们程序就直接退出,因为申请失败也没有必要进行操作;}printf("%p\n", p);int* p= (int *)realloc(p, 10000);//追加字节,后共10000个字节;printf("%p\n", p);free(p);p=NULL;return 0;
}

常见的动态内存的错误

1.对空指针解引用

void test()
{int* p = (int*)malloc(1000000000 * 10000000*10000000);//由于申请的空间过大而申请失败返回空指针;*p = 20;//当p为NULL时就会有问题;free(p);p = NULl;}

2.对动态开辟的空间越界访问

int* p = (int*) = malloc(sizeof(int) * 5);//申请5个int的空间
if (p = NULl)
{exit;
}
for (int i = 0; i < 10; i++)//却访问10个int的空间
{*(p + i) = i;
}

3.对非动态开辟的空间进行free释放

void test()
{int a = 10;int* P = &a;free(p);//OK?
}

4.使用free释放一块空间的一部分

void Get()
{int*p = (char*)malloc(100);p++;free(p);//p不在指向动态内存的起始位置;
}

5.对同一块动态内存多次释放

void Get()
{int*p = (char*)malloc(100);free(p);free(p);
}

6.动态内存忘记释放

7.

void Get(char* p)
{p = (char*)malloc(100);
}
void test()
{char* str = NULL;Get(str);//以变量的方式传参;无法做到str的修改;strcpy(str, "hello");printf(str);
}

运行的时候程序会崩溃,而且存在内存泄漏;

str以值的形式传参给p;p是Get的函数的形参,只能在函数内部有效,等Get函数返回之后,动态开辟的空间还未释放,并且无法找到,就会存在内存泄漏。

动态内存分布——malloc,calloc,realloc,free的使用。以及关于动态内存的常见错误。相关推荐

  1. 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现

    内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...

  2. C语言动态申请内存空间之malloc(),calloc(),realloc()函数

    在C语言中用于动态申请内存空间的函数主要为malloc()函数,calloc()函数,以及realloc()函数,以下主要介绍三个函数的用法,区别以及使用时的注意事项. malloc(),calloc ...

  3. c语言释放内存函数,【C语言】内存分配函数malloc/ calloc/ realloc及内存释放free

    前言: 内存区域划分与分配: 1.栈区(stack)--程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等,程序结束时由编译器自动释放. 2.堆区(heap) -- 在内存开辟另一块存储区域 ...

  4. c语言malloc,calloc,realloc函数介绍

    malloc,calloc,realloc动态内存管理函数的出现解决了在某些c语言标准中不能使用变长数组的问题 这三个函数的使用需要头文件stdlib.h,这些函数开辟的空间在堆区,系统不会自动释放, ...

  5. malloc calloc realloc 三兄弟!!!

    学习过C语言的都知道 malloc calloc realloc 这三个函数,这三个函数都是用于动态的分配内存的,最后都要使用 free函数进行释放. 这三个函数的头文件 : stdlib.h 在li ...

  6. malloc calloc realloc的对比

    函数原型 三个函数的声明分别是: void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* call ...

  7. malloc/calloc/realloc

    malloc/calloc/realloc和free介绍: malloc函数 malloc函数可以从堆上获得指定字节的内存空间,其函数声明如下: void * malloc(int n); 参数释义: ...

  8. C语言学习笔记10-指针(动态内存分配malloc/calloc、realloc、释放free,可变数组实现;Tips:返回指针的函数使用本地变量有风险!;最后:函数指针)

    C语言:指针 1. 指针:保存地址的变量 *p (pointer) ,这种变量的值是内存的地址.   取地址符& 只用于获取变量(有地址的东西)的地址:scanf函数-取地址符   地址的大小 ...

  9. C++自学21:动态分配内存(malloc/calloc/realloc/new)/回收内存(free/delete)

    一:malloc函数,请求系统分配内存 // 让系统分配8个字节的内存,这8个字节是连续的,就是一个数组 int* a=(int*)malloc(8); // 如果分配成功,则返回数组首字节的地址,分 ...

最新文章

  1. BZOJ 2342 [Shoi2011]双倍回文(manacher+并查集)
  2. Spring Enable annotation – writing a custom Enable annotation
  3. openfire SparkWeb 安装配置
  4. Ubuntu 16.04下使用gcc输出汇编的.0文件为可执行文件时出现:`_start'被多次定义
  5. 电脑装机人员、管理软件安装实施人员必备工具包使用教程汇总值得收藏
  6. 【学习笔记】JAVA快捷键
  7. Linux中光驱对应的设备文件,Linux硬盘对应的设备文件
  8. PowerDesign安装教程
  9. 我关注的一周技术动态 2015.8.23
  10. 强化学习10——迭代学习
  11. cygwin linux 教程,Cygwin工具使用入门教程
  12. mpa和pis_有关压力单位pis
  13. 宏定义有无参数宏定义和带参数宏定义两种
  14. 人工智能有哪些好处???
  15. 《深入理解Android内核设计思想(第2版)(上下册)》之Android源码下载及编译...
  16. ExtJS教程(3)--- Ext中类的使用
  17. GT工具中用到的英文词解释
  18. 互联网大佬们齐聚首,除了演讲还有啥?点击All in 全部热点!
  19. iPhone 6 上被封印的技术,将会被这家公司带到 Android
  20. 生存战争2.2联机版游戏介绍

热门文章

  1. C语言小项目--打地鼠
  2. 利用云服务器实现不同局域网的电脑进行远程控制
  3. 文件服务器 选型,普通文件存储服务器选型原则
  4. 微众银行首席AI官杨强:联邦学习理论基础、四大应用场景与微众的AI全布局
  5. Check your file - it most likely has keys in far negative or positive timeline.
  6. Word中的表格插入图像,不能平铺表格内
  7. 水仙花数python代码for_水仙花数如何用python代码表示?
  8. 校园O2O商铺平台-店铺列表展示功能
  9. boost uuid
  10. java操作ffmpeg为视频添加背景音乐