C语言中灵活多变的动态内存,malloc函数 && free函数&& calloc函数 && realloc函数

03-10 1111阅读

C语言中灵活多变的动态内存,malloc函数 && free函数&& calloc函数 && realloc函数

文章目录

  • 🚀前言
  • 🚀管理动态内存的函数
    • ✈️malloc函数
    • ✈️free函数
    • ✈️calloc函数
    • ✈️realloc函数
    • 🚀在使用动态内存函数时的常见错误
      • ✈️对NULL指针的解引用
      • ✈️ 对动态开辟空间的越界访问
      • ✈️对非动态开辟内存使用free释放
      • ✈️使用free释放一块动态开辟内存的一部分
      • ✈️对同一块动态内存多次释放
      • ✈️动态开辟内存忘记释放(内存泄漏)

        🚀前言

        铁子们好啊!今天阿辉给大家讲一下C语言里面特别重要的一块知识——动态内存管理,为什么说它重要呢?相信大家在使用数组时都遇到过数字开辟空间太大或者太小的情况,这是很尴尬的因为数组空间一旦确定就难以扩大或者缩小。而今天的动态内存管理将帮我们很好的解决这一窘境。话不多说,开始咱们今天的学习吧!!!

        🚀管理动态内存的函数

        动态内存的管理其实也就分为两块

        • 空间的开辟和扩容
        • 空间的释放

          而要做到以上两点,我们要引入几个重要的管理动态内存的函数

          动态内存的开辟和释放都是在堆区上

          ✈️malloc函数

          malloc函数是用来开辟空间的,如何使用呢?下面是它的声明👇

          void* malloc(size_t size);
          

          关于malloc函数的注意事项:

          • size表示malloc函数所开辟空间的大小,单位是字节
          • maloc函数对于开辟空间存放何种类型的数据并不关心,返回值是void*类型,malloc开辟空间成功,则返回这块空间的起始位置的地址;若开辟空间失败,则返回空指针NULL
          • 给malloc传入的参数为0时,这种行为是C语言标准未定义的,取决于编译器
          • 由malloc函数开辟的空间,里面的内容是随机的

            具体使用:

            int mian()
            {
            	int* p = (int*)malloc(sizeof(int) * 10);//开辟10*4个字节的空间,返回值强转为int*
            	if (p == NULL)//判断动态内存是否开辟成功
            	{
            		printf("malloc 开辟空间失败\n");//开辟失败返回调试语句,就是让程序员知道哪错了
            		return 1;//开辟失败直接返回
            	}
            	//对动态开辟内存的进一步使用
            	//这玩意其实就是个数组,有了首元素地址,不就是当成数组来玩嘛
            	for (int i = 0; i  
            

            关于malloc函数开辟的空间,它是一块连续的空间,直接当成数组使用一点毛病没有,

            它与数组最大的区别在于,malloc开辟的空间是在堆区上的,而数组是在栈区上的。

            而堆区上申请的空间须有程序员自己手动释放(Java,Python有垃圾回收机制),否则将造成内存泄漏。其实就是你从我这拿了空间去用,不用了就还给我,别占着茅坑不拉屎,你不用别人也用不了。对于堆区申请的空间的释放,这里要引入下面这个新的函数

            ✈️free函数

            C语言提供了一个函数free,专门用来做动态内存的释放和回收的,函数声明如下:

            void free(void* ptr);
            

            对于free函数使用时的注意事项:

            • 对于传给free的参数必须是指向动态开辟内存(也就是是堆区开辟的空间)的起始地址的指针
            • 若传给free的参数是空指针NULL,free函数则什么也不干
            • free只会释放传入的指针指向的空间,并不会给传入指针置空,这会很危险,空间你都还给操作系统了,你这个指针还指向那里,这个指针很野得治,所以free完,指针我们要置空
              int mian()
              {
              	//开辟动态空间
              	int* p = (int*)malloc(sizeof(int) * 10);
              	//判断动态内存是否开辟成功
              	if (p == NULL)
              	{
              		printf("malloc 开辟空间失败\n");
              		return 1;
              	}
              	/*
              	对动态开辟空间的使用
              	*/
              	//不用啦,释放空间
              	free(p);
              	p = NULL;
              	return 0;
              }
              

              👆这段代码就是动态内存的使用的基本模式,先开辟空间,然后判断是否开辟成功,接着使用这块空间,最后不用了把这块空间释放掉

              ✈️calloc函数

              C语言中还提供了calloc函数,同样是进行动态内存分配的,函数声明如下:

              void* calloc(size_t num, size_t size);
              

              calloc与malloc仅有两点不同

              • 使用上calloc函数需要两个参数,开辟空间为num个大小为size个字节的空间
              • calloc函数开辟的空间会把每个字节全部初始化为0
                int main()
                {
                	int* p = (int*)calloc(10, sizeof(int));
                	if (p == NULL)//判断空间是否开辟成功
                	{
                		printf("calloc开辟空间失败\n");
                		return 1;
                	}
                	for (int i = 0; i  
                

                输出:

                0 0 0 0 0 0 0 0 0 0  //十个0
                

                ✈️realloc函数

                铁子们估计有点不买账了,说好的动态内存分配,讲了这么多也没有体现动态俩字。铁子们别急,realloc函数才是今天的重头戏

                C语言提供realloc函数用来使动态内存的使用更加灵活,之前开辟的空间太大或者太小都可以灵活的调整重新分配空间大小

                realloc函数的函数声明

                void* realloc(void* ptr,size_t size);
                

                realloc函数在使用时要注意下面这几点:

                • ptr是要调整的空间的起始地址,ptr得是动态内存开辟的地址,若是ptr为空指针,realloc函数将与malloc函数的实现一样

                • size是realloc函数调整大小后的内存空间大小

                • realloc函数的返回值是空间调整后的起始地址,空间开辟失败返回空指针

                • realloc函数扩容的空间里面的值并未被初始化,是随机值

                • 这个函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

                • 对于realloc函数调整空间有了两种情况:

                  • 情况一:原有空间后有足够空间

                    C语言中灵活多变的动态内存,malloc函数 && free函数&& calloc函数 && realloc函数

                  • 情况二:原有空间后无足够空间,原有空间将被释放掉,重新找一块空间

                    C语言中灵活多变的动态内存,malloc函数 && free函数&& calloc函数 && realloc函数

                    例子:

                    int main()
                    {
                    	int* p = (int*)malloc(5 * sizeof(int));//先用malloc申请5个整型大小的内存空间
                    	if (p == NULL)//判断是否开辟成功
                    	{
                    		printf("malloc开辟空间失败\n");
                    		return 1;
                    	}
                    	int i = 0;
                    	for (i = 0; i  
                    

                    上述,使用realloc对空间做调整时,一定要新创建一个变量来接收realloc的返回值,因为如果使用指向原空间的起始地址的指针p来接收,一旦realloc开辟空间失败,p将被赋值成NULL,将找不到原来空间造成内存泄漏

                    🚀在使用动态内存函数时的常见错误

                    ✈️对NULL指针的解引用

                    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 
                    		*(p + i) = i;//当i是10的时候越界访问
                    	}
                    	free(p);
                    }
                    
                        int a = 10;
                        int *p = &a;
                        free(p);//error——不能对非动态内存进行释放
                    }
                    
                        int *p = (int *)malloc(100);
                        p++;
                        free(p);//p不再指向动态内存的起始位置
                    }
                    
                        int *p = (int *)malloc(100);
                        free(p);
                        free(p);//重复释放
                    }
                    
                        int *p = (int *)malloc(100);
                        if(NULL != p)
                        {
                            *p = 20;
                        }
                    }
                    int main()
                    {
                        test();
                        while(1);
                    }
                    
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]