动态内存开辟

本文探讨一下动态内存开辟的方法和使用时常见的问题                                                 ——前言

1.动态内存开辟方法

在c语言当中,我们可以利用动态内存开辟函数在内存中的堆空间中开辟动态空间,动态空间的特点是可以根据程序来调整申请空间的大小,由此可以节省空间,减少浪费。

1.1动态内存开辟函数

1.void* malloc (size_t size):

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

malloc函数的参数size的值是需要开辟的空间大小,单位是字节。

如malloc(2)的意思是在堆空间开辟两个字节的空间。

malloc的返回参数是指针类型参数,具体的返回类型可根据需要进行调整。

2.void* calloc (size_t num, size_t size):

calloc函数的功能是为 num 个大小为 size 的元素开辟一块空间,开辟空间大小为size*num。并且把空间的每个字节初始化为0。

calloc与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

3.void* realloc (void* ptr, size_t size)

realloc函数的作用是将ptr指针指向的动态内存空间的大小改变为size。

此函数用于改变一块已有的动态内存开辟空间,他在开辟空间的时候存在两种情况。

情况1:原有空间之后有足够大的空间

当原有空间之后有足够多的空间足够我们使用时,realloc函数会在原有空间之后开辟一块空间。

情况2:原有空间之后没有足够大的空间

此时realloc函数会内存中找一块新的连续空间,并将原有空间中的内容拷贝到新的空间中。

1.2动态内存开辟方法

我们用malloc,calloc函数分别开辟两个字节的空间,再用realloc函数将空间扩展成4个字节

1.2.1 用malloc开辟 2 个字节空间

int* ptr=(int*)malloc(2);
if(ptr!=NULL)
{
  ptr="1";
}

如图所示,我们用ptr指针指向malloc开辟空间的头部,这时我们需要对ptr进行检测,如果ptr!=NULL,说明空间开辟成功,否则开辟失败。

1.2.2 用calloc开辟 2 个字节空间

int* ptr2=(int*)calloc(2,1);
if(ptr2!=NULL)
{
  ptr2="1";
}

1.2.3 用realloc函数将ptr指向的空间调整为 4 个字节

int* ptr3=(int*)realloc(ptr,4);
if(ptr3!=NULL)
{
  ptr3="123";
}

1.3 释放动态开辟的空间

当我们使用完动态空间时,如果不主动释放空间,这块空间也不能被其他人使用,会被白白浪费掉。因此我们要用free函数将这块空间还给操作系统,以便他人使用。

void free (void* ptr)

ptr是指向动态空间的指针。

1.4 将指向动态内存开辟空间的指针置空

当我们free完空间时,指针ptr就失去了对该空间的所有权,尽管他还保存着该空间的地址。因此我们需要将他置空,防止他变成野指针,对野指针的操作会造成非法访问的问题。

综上所述:一个标准的完整程序写法如下:

int* ptr=(int*)malloc(2);
if(ptr!=NULL)
{
  ptr="1";
}
free(ptr);
ptr=NULL;

2.常见问题

2.1:

1  void GetMemory(char *p)
2 {
3   p = (char *)malloc(100);
4 }
5  void Test(void)
6 {
7   char *str = NULL;
8   GetMemory(str);
9   strcpy(str, "hello world");
10  printf(str);
11 }

请问运行Test 函数会有什么样的结果?

1.第8行代码将str的值传递给形参p,,并在函数GetMemory中对p进行赋值。此操作并不能改变str的值,因此str依然是空指针。

2.第9行将hello world字符串拷贝到空指针,非法访问内存,引发程序崩溃

3.此程序结束后并没有对动态内存进行释放,也没有将指针置空,因此存在内存泄漏问题。

2.2:

1	 char *GetMemory(void)
2	{
3		char p[] = "hello world";
4		return p;
5	}
6	void Test(void)
7	{
8		char *str = NULL;
9		str = GetMemory();
10		printf(str);
11	}

请问运行Test 函数会有什么样的结果?

此程序结束后并没有对动态内存进行释放,也没有将指针置空,因此存在内存泄漏问题。

2.3:

1     void GetMemory(char **p, int num)
2  {
3	  *p = (char *)malloc(num);
4    }
5      void Test(void)
6   {
7	 char *str = NULL;
8	 GetMemory(&str, 100);
9	 strcpy(str, "hello");
10	 printf(str);
11   }

请问运行Test 函数会有什么样的结果?

此程序结束后并没有对动态内存进行释放,也没有将指针置空,因此存在内存泄漏问题

2.4:

1    void Test(void)
2  {
3	char *str = (char *)malloc(100);
4	strcpy(str, "hello");
5	free(str);
6	if (str != NULL)
7	{
8		strcpy(str, "world");
9		printf(str);
10	}
11   }

请问运行Test 函数会有什么样的结果?

1.第5行对str指向的空间已经释放,未将str置空,str仍然保存malloc指向的空间,str不为NULL。

2.第8行将“world”放到str指向的空间中,属于非法访问,因此程序在第8行崩溃。


版权声明:本文为shuangge110原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。