当前位置: 首页 > wzjs >正文

网站开发 工具做门户网站的营业范围

网站开发 工具,做门户网站的营业范围,大数据营销精准营销,wordpress导航链接地址都是主页目录 1.什么是动态内存? 2.为什么要使用动态内存分配空间? 3.动态内存开辟函数malloc,calloc,realloc 3.1 malloc 3.2 calloc 3.3 realloc 3.4 头文件包含 4.动态内存释放函数free 5.动态内存的基本常见错误 5.1 对NULL…

目录

1.什么是动态内存?

2.为什么要使用动态内存分配空间?

3.动态内存开辟函数malloc,calloc,realloc

3.1 malloc

3.2 calloc 

3.3 realloc

3.4 头文件包含

4.动态内存释放函数free

5.动态内存的基本常见错误

        5.1 对NULL的解引用操作

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

5.3 误对非动态内存进行释放

5.4 使⽤free释放⼀块动态开辟内存的⼀部分

5.5 动态开辟内存忘记释放(内存泄漏)

6.c/c++中的内存区域划分

1.什么是动态内存?

        从内存区域上来看,一般的静态变量,比如

int a;
char c;
int arr[10]={1,2,3,4,5};
char arr2[10]="abcde";
int *p1;
char *p2;
double d;

        诸如此类都是在栈空间分配的,定义是不会变的,固定死的,使用完后由系统自动释放空间。而动态内存,是在堆区开辟的,由用户开辟,用户释放,系统不会主动进行释放操作。可以根据实际需求对内存分配进行扩大。

2.为什么要使用动态内存分配空间?

        在上述代码中,都是静态内存,有那么几个缺点:

  • 无论是变量,整形数组,字符串数组亦或是指针,内存大小都是固定的,一旦确定不可更改。
  • 数组在申明的时候必须要确定长度,数组空间确定了也不可以改变。

        那么在后续使用中,这种静态内存分配不可能满足所有需求,很多程序在运行后会越来越大,我们也无法准确预知程序所需要的内存空间到底是多少,所以需要更加灵活的方式来定义内存空间,程序就不会崩溃。所以可以由用户手动开辟,手动释放的方式——动态内存分配诞生了。

3.动态内存开辟函数malloc,calloc,realloc

        C语言库中提供了几种内存开辟函数,malloc,calloc和realloc,这些都有不同的功能。一一介绍

3.1 malloc

        malloc在cplusplus中是这样的,其实动态内存函数在之前的通讯录优化扩容部分是有提及并且使用它去开辟过数组空间的。它会申请一块连续的空间,并且返回一个指向内存块开头的指针,内存块中数据是未初始化的。

        如果开辟失败,则会返回一个NULL的指针,所以要对返回值进行检查。

        由于返回的类型是void*,所以malloc的时候要强制转化。

malloc

举个例子:

int main()
{//申请空间int*p =(int*)malloc(60);if (p==NULL){perror("malloc");return 1;}int arr[] = {0};int i = 0;for (int i = 0; i < 10; i++){*(p + i) = i + 1;}for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;
}

指针p的变化:可以看出是随机的(调试界面)

3.2 calloc 

        calloc是C语言提供的另外一种动态内存开辟的方法,它和malloc不同在于它在开辟之初能直接初始化内存空间为0。开辟的是num个大小为size元素

calloc

例子:

int main()
{int* p = (int*)calloc(10,sizeof(int));if (p==NULL){printf("%s\n",strerror(errno));return 1;}int i = 0;/*for ( i = 0; i < 10; i++){*(p + i) = i;}*/for (i = 0; i < 10; i++){printf("%d ", p[i]);}free(p);p = NULL;return 0;
}

 调试界面的变化:可以看出p是被初始化为0了。

不去对指针进行任何赋值操作,输出结果是: 

赋值后是:

3.3 realloc

         realloc也是一个动态开辟的方法,不过它相较于malloc和realloc更为灵活。来看看它的属性

realloc

        这个单词的前缀是re,而在英语单词中re的意思是重新,再次的意思。所以realloc是重新申请一块内存块。有时会我们发现申请的空间太小了,有时候我们⼜会觉得申请的空间过大了,那为了合理的使用,我们对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。

  • ptr是要调整改变的内存地址
  • size是对内存要重新分配多少空间。
  • 返回重新调整后的内存起始地址
  • 在调整内存的新大小之后,会根据情况不同有两种情况
  1. 如果原来空间够大,即是原地扩容,在原来空间中追加空间。
  2. 空间中所剩余的空间不够分配后续的空间,就会另外找一块足够大的空间,这个空间不一定和原空间地址连续。开辟后,会把原空间的数据拷贝到新空间,然后返回新内存块的起始位置。

举个例子:

int main()
{int* p = (int *)malloc(40);if (p==NULL){perror("malloc");return 1;}int i = 0;for ( i = 0; i < 5; i++){*(p + i) = i;}//不够了,进行扩容int* ptr = (int *)realloc(p,1000);if (ptr!=NULL){p = ptr;}for ( i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;
}

        调试界面中,一开始指针的地址p是这样的。

        再走下去到这一步,我们把realloc的地址给了指针ptr存放,可以看出p指向的地址和ptr指向的地址不同,再把ptr赋值给p,p一定会变成ptr的地址

 F10走

 (至于为什么原地空间不够大,是因为我扩容了1000个字节,如果只扩容40,100),我想应该是原地扩容,地址不会变动,可以自行尝试。

这是不同情况下realloc的空间示意图,是在通讯录第二篇有画过的。

3.4 头文件包含

        开辟函数malloc,calloc,realloc和释放函数free都是要包含头文件的,<stdlib.h>声明就可以了。

4.动态内存释放函数free

        free函数是专门为了上面三个扩容函数准备的。为什么要free呢,因为静态内存是系统自己在栈区开辟的,你去使用只需要负责用,用完系统自动回收销毁空间。而动态内存是手动开辟的。就可以不用太正式的语言,举个很通俗易懂的比方就是。

        就好比你去餐厅吃饭,这就是静态开辟,你所做的是点菜,吃饭,结账。剩下都是餐厅要做的事情。餐厅要洗菜,切菜,做菜,最后你吃完要打扫餐桌,洗碗,处理厨余垃圾。系统就是餐厅,静态内存就是你吃的菜。

        而你觉得餐厅的饭可能是预制菜,不和你胃口,不营养,你想自己在家做一桌好吃的菜。那就是动态开辟,一切都要自己动手,从买菜,做菜,吃饭到收拾。前面是malloc/calloc/realloc开辟,收拾就是你要free,不free就好比你不收拾,要么菜都发霉了,引来虫子,细菌,然后你被家长教育一顿。而在编程里,不主动free置NULL,系统就会崩溃,内存泄漏,野指针等等问题。

        free的使用很简单,就是把内存开辟所在的指针变量释放,置NULL就可以了。free只是释放了空间,要置空才行,如果不置空,指针变量依然指向那块内存,内存的地址是还在的。在以后的代码中若不小心继续调用指针变量,会出现不可预料的错误。

我特意去调试了一下看看区别:

        这是free后还没置NULL的内存地址,断点在50行,走一步,free了,内存地址不变(因为我是重新调试,地址是系统随机分配的,所以地址不可能和上面的保持一致),还在!只是内存所存放的内容成了随机值。那去访问一个随机值的内存空间,一次两次没事是侥幸,但肯定是有问题的,还是要严谨。

再走一步就是变成了0x00000000,且不可读取内存,说明是NULL。 

5.动态内存的基本常见错误

        5.1 对NULL的解引用操作

 void test() 
{ 
int *p = (int *)malloc(INT_MAX/4);    *p = 20;//如果p的值是NULL,就会有问题 free(p);}

        在编译器里,*p那一行会产生警告,说是取消对null的解引用操作,其实就是在前面没有对指针p进行检查是否为空,因为系统可能无法一次性分体量为(INT_MAX/4)的内存空间给指针p。很可能存在开辟失败,就成了空指针。而*p=20,是空指针的话显然是有问题的。

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

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); 
}

        内存只开辟了40个字节,而i到10的时候是0-10,有11个数据,所以是越界访问。 

5.3 误对非动态内存进行释放

void()
{
int a =10;
int *p =&a;
free(p);
}

        这对吗?肯定是错的,你都没有malloc内存函数开辟空间,就要free,想free什么? 

5.4 使⽤free释放⼀块动态开辟内存的⼀部分

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

        这是我有时候会犯的错误,经常会报警告,后来DeepSeek一查才直到p++后会使指针不指向起始位置,产生局部释放 ,AI的辅助有时候使让人一下顿悟。

5.5 动态开辟内存忘记释放(内存泄漏)

void test() 
{  int *p = (int *)malloc(100); if(NULL != p)     {        *p = 20;  } 
}
int main()
{
test();
return 0;
}

       没有在函数中进行动态开辟内存释放,引发内存泄露问题。函数调用结束后就销毁了,内部没有进行释放,也就释放不了了。

        忘记释放不会复用动态开辟的空间会造成内存泄漏。

        切记:动态开辟的空间⼀定要释放,并且正确释放。         

6.c/c++中的内存区域划分

        关于动态内存的开辟知识 ,在c语言只是涉及,而在后续学习数据结构中,会不断学习 。数据结构中malloc,calloc,realloc和free会不断,频繁见面的。所以还是需要熟练的掌握和使用。

http://www.dtcms.com/wzjs/596934.html

相关文章:

  • 想自己做微信网站的工作wordpress网站有多大
  • 网站职位推荐怎么做在线花钱做网站
  • 网站建设5000费用预算如何避免网站被耍流量
  • 高端网站建设网站建设项目招标在什么网站公示
  • 网站开发的推荐网站建设网站目的模板
  • 商城网站设计教程做阀门的英文网站怎么写
  • 天津网站建设找哪家如何看待响应式网页设计
  • 焦作会做网站制作的有哪家乐清网站建设yq01
  • 泰州市住房和城乡建设局官方网站房屋装修效果图三室一厅
  • wordpress学校站模板外贸网站建设优化推广
  • 网页设计与网站建设考试名词解释2019网站的推广
  • 主机屋怎么做网站彭州建设局网站
  • 网站推销怎么做ppt模板服务平台官网
  • 哪家网站建设公司湖北正规网站建设质量保障
  • 建设个电影网站多少钱馆陶网站建设
  • 网站开发前后端技术wordpress搬家后台还是老网站
  • 刷赞网站推广软件wordpress的标题怎么修改
  • 网站不做icp备案大连app开发公司排名
  • 提取网站子页面邮箱网站的标签修改
  • 怎么自己制作一个网站的书源北京最大专业网站建设
  • 棋牌网站开发工程师遵义网上房地产
  • 公司地址seo服务工程
  • 东莞营销网站建设优化公司网站建设如何做账
  • 网站如何做绿标大庆工程建设公司网站
  • 西充县规划建设局网站wordpress怎么实现注册功能
  • 网站开发用哪个程序做免费小说网站怎样赚钱
  • 广州知名网站建设西安百度推广多少钱
  • 新手建什么网站赚钱做网站详细教程
  • 建设一个网站需要考虑什么重庆市建设工程信息网安全监督下载中心
  • 网站建设公司在哪里宣传网页设计简约