您的位置:首页 > 健康 > 养生 > 广州国外建站模板_网站外链建设方法_千度seo_外链群发

广州国外建站模板_网站外链建设方法_千度seo_外链群发

2024/12/23 16:57:40 来源:https://blog.csdn.net/qq_58135952/article/details/144102299  浏览:    关键词:广州国外建站模板_网站外链建设方法_千度seo_外链群发
广州国外建站模板_网站外链建设方法_千度seo_外链群发

目录

1.动态内存函数

1.1.malloc和free函数

1.2.calloc函数

1.3.realloc函数

1.4.总结

2.常见的动态内存错误

2.1.对NULL指针的解引用操作

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

2.3.对非动态开辟内存使用free释放

2.4.使用free释放一块动态开辟内存的一部分

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

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

2.7.总结


前言:为什么要有动态内存管理呢?

        之前我们在学习创建变量、数组,等等都是申请空间来放置数值;一旦申请之后,空间的大小不会再改变。本文将介绍C语言中申请内存大小的函数 malloc、calloc、realloc、free,以及对内存函数使用时候常见的错误。若有错误,请各位指正。

1.动态内存函数

        动态内存函数是针对堆区来说的,下图是内存的大致划分,静态内存就是静态区中的全局变量和静态修饰的局部变量。如下代码是static修饰的局部变量,属于静态区。

static a = 0;

1.1.malloc和free函数

1.功能:

  malloc:向内存申请一块连续可用的空间,返回指向这块空间起始的指针;

  free:   释放动态开辟的内存。

2.使用形式

void* malloc (size_t size);
void free (void* ptr);

malloc函数

1.void* 返回值类型为空指针,需要强转换再使用,申请成功返回内存块起始指针,申请内存失败,返回位空指针;

2.size 内存块的大小,字节位单位,size_t无符号整型;

注意:

1.malloc函数申请的空间是不会初始化的,内存块不初始化是随机值。

2.在free释放内存块之后,void* 函数的返回值保留之前的开辟内存块的时候指针变量,

如果再访问就是非法访问了,因此使用完内存空间要将返回值置为NULL,可看示例。

free函数

1.viod没有返回值;

2.ptr 指向先前使用或者分配的内存块的指针,如果ptr是空指针NULL,则函数不会执行任何操作。

注意:free函数的形式参数(ptr)是指向动态内存空间的变量。

3.示例

(1)正常使用

#include <stdio.h>
#include <stdlib.h>
int main ()
{//申请动态内存空间int* p = (int*)malloc(40);//判断是否申请成功,并强制转换为整型if (p == NULL){perror("malloc");return 1;}//赋值int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}//输出for (i = 0; i < 10; i++){printf(" %d",*(p + i) ); }return 0;//用完之后返回给堆区,以便下次的调用free(p);p = NULL;
}

(2)申请错误的案例

#include <stdio.h>
#include <stdlib.h>
int main()
{//申请动态内存空间int* p = (int*)malloc(INT_MAX);//INT_MAX宏定义,表示int中最大的值2147483647//16进制是0x7FFFFFFF//判断是否申请成功,并强制转换为整型if (p == NULL){perror("malloc");return 1;}free(p);p = NULL;
}

        INT_MAX问宏定义,表示int 整型中最大的值,2147483647,开辟空间可能已经超过给函数分配的空间,输出的结果是没有足够的空间。

(3)越界访问示例

#include <stdio.h>
#include <stdlib.h>
int main()
{//申请动态内存空间int* p = (int*)malloc(40);//判断是否申请成功,并强制转换为整型if (p == NULL){perror("malloc");return 1;}free(p);p = NULL;//赋值int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}
}

这种情况下是无法写入的。

(4)free函数释放非动态空间

#include <stdio.h>
#include <stdlib.h>
int main()
{int a = 0;int* p = &a;//创建非动态空间的指针free(p);}

        释放非动态空间的指针会直接报错的。

1.2.calloc函数

1.功能:Allocate and zero-initialize array分配内存并将其初始化为0.

2.使用形式:

void* calloc (size_t num, size_t size);

1.void* 同上;返回值是指向调整之后内存的起始位置;

2.num:分配元素的个数;;

3.size:每个元素的大小;

注意:

1.calloc函数和malloc函数不同,申请空间之后会将其 初始化为0;其余的作用基本一样。

3.示例

#include <stdio.h>
#include <stdlib.h>
int main()
{int* p1 = (int*)malloc(10 * sizeof(int));int* p2 = (int*)calloc(10 ,sizeof(int));//两者的表达方式相似,只是*改为了,//判断是否申请成功if (p1 == NULL){perror("malloc");return 1;}else if (p2 == NULL){perror("calloc");return 1;}//使用int i = 0;for (i = 0; i < 10; i++){*(p2 + i) = i;}//输出for (i = 0; i < 10; i++){printf(" %d",*(p2 + i) ); }free(p1);free(p2);p1 = NULL;p2 = NULL;return 0;
}

        其中p1是malloc函数申请的内存,p2是calloc申请的内存,可以看出calloc函数在申请完内存之后就会初始化为0.

1.3.realloc函数

1.功能:Reallocate memory block,重新分配内存块的大小,扩展原有的内存块,或者申请新的内存块,

特点:保留之前的内存中的数据

2.使用形式:

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

1.void* 同上,返回值是指向调整之后内存的起始位置;

2.ptr     先前使用或者分配的内存块的大小;

3.内存块的大小。

注意:

1.和malloc一样不会初始化空间;

2.申请空间失败的将返回NULL空指针;

3.如果ptr是空指针,则该函数的行为类似于 malloc,分配一个新的字节块并返回一个指向其开头的指针;

4.realloc函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

5.realloc函数是重新申请内存块,不是追加在malloc内存空间的内存块,是将原本的空间扩展到size的大小,整个内存块空间的大小就是size,和malloc再开辟的空间相比,函数只是可以保留剩之前已经赋值的内存空间。

4.realloc调整内存空间的两种情况

        假设 malloc函数申请了5个整型的空间,但是不够是使用了,要是使用 realloc函数将malloc 的空间扩展为10个整型的空间,可以分为两种情况。假设其返回值分别为p1和p2。

(1)p1==p2的情况

        malloc申请的空间可以扩容,可以在后面直接续上新的空间,malloc函数返回值和realloc函数的返回值是一样的。

(2)p1!=p2的情况

        当malloc申请的空间后面没有足够的空间扩容,realloc函数会重新昭仪满足空间大小的连续的空间把就得空间数据,拷贝到新空间的对应的位置,并把旧的空间释放掉,同时返回新的内存块的起始位置。

3.示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{int* p = (int*)malloc(5*sizeof(int));//申请5个整型数据的空间if (p == NULL){perror("malloc");return 1;}int i = 0;for (i = 0; i < 5; i++){*(p + i) = i;}int* str = realloc(p, 10* sizeof(int));//重新申请的内存空间if (str == NULL){perror("realloc");return 1;}else{p = str;//情况1,空间已经被释放了,p=str;//情况2, 新开辟的内存空间,之前malloc开辟的空间已经释放,p不为NULL//如果统一使用,建议使用p}for (; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf(" %d", *(p + i));}free(str);//realloc函数延续之前分配的空间继续使用或者释放掉之前的空间,p = NULL;str = NULL;return 0;}
1.4.总结

        malloc函数和realloc函数申请的函数空间不会初始化,calloc申请的函数空间会初始化,realloc申请的空间是在malloc和calloc空间后面的追加,free配合前面的三个函数使用。动态内存函数所设计到的操作系统的设置我不会啊,所以没有能力模拟函数实现。

2.常见的动态内存错误

2.1.对NULL指针的解引用操作
#include <stdio.h>
#include <stdlib.h>
void test()
{int *p = (int *)malloc(INT_MAX );*p = 20;//如果p的值是NULL,就会有free(p);
}
int main()
{test();return 0;
}

        上述的代码中malloc函数没有申请成功内存空间,也不会报错出错误在哪里,因此在对返回指针进行解引用操作的之前需要判断是否为空指针。

2.2.对动态开辟的空间的越界访问
#include <stdio.h>
#include <stdlib.h>
int main ()
{//申请动态内存空间int* p = (int*)malloc(100);//判断是否申请成功,并强制转换为整型if (p == NULL)//判断是否为空指针{perror("malloc");return 1;}//赋值int i = 0;for (i = 0; i < 100; i++){*(p + i) = i;}//用完之后返回给堆区,以便下次的调用free(p);p = NULL;return 0;
}

如果越界访问,程序就会挂了,表现得现象就是程序窗口光标

2.3.对非动态开辟内存使用free释放
#include <stdio.h>
#include <stdlib.h>
int main()
{int a = 10;int *p = &a;free(p);p = NULL;return 0;
}

会报错的

2.4.使用free释放一块动态开辟内存的一部分
#include <stdio.h>
#include <stdlib.h>
int main()
{//申请动态内存空间int* p = (int*)malloc(100);//判断是否申请成功,并强制转换为整型if (p == NULL){perror("malloc");return 1;}//赋值int i = 0;for (i = 0; i < 25; i++){*p = i;p++;}//用完之后返回给堆区,以便下次的调用free(p);p = NULL;return 0;	
}
2.5.对同一块动态内存多次释放
#include <stdio.h>
#include <stdlib.h>
int main()
{//申请动态内存空间int* p = (int*)malloc(100);//判断是否申请成功,并强制转换为整型if (p == NULL){perror("malloc");return 1;}free(p);//用完之后返回给堆区,以便下次的调用free(p);p = NULL;return 0;	
}
2.6动态开辟内存忘记释放(内存泄漏)
#include <stdio.h>
#include <stdlib.h>
int main()
{int i = 1;int* p=&i;while (i--){p = (int*)malloc(20);}free(p);return 0;
}

上述的案例是申请了一次的内存块,电脑运行的内存几乎没有变化。

内存不释放的情况下,

#include <stdio.h>
#include <stdlib.h>
int main()
{while (1){malloc(20);}return 0;
}

        运行上述程序之后,内存的会增大的,截取不到变化的之后的数值。

         程序的设计限制了开辟内存空间的大小,如果不限制,程序一直运行下造成的内存泄漏,会导致计算机的性能下降,系统不稳定,资源的浪费等等。

2.7.总结

1.内存空间的开辟之后需要对返回的指针判断是否为NULL;

2.申请的内存空间要满足所存储数据的大小,不可访问越界;

3.内存申请函数和free函数配合使用,且释放之后将动态内存函数的返回值置为NULL;

4.不可释放多次内存空间;

5.动态内存使用完毕,一定要释放空间。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com