C语言—动态内存分配相关知识详解


目录

一.前言

二.动态内存函数详解及其使用

2.1 malloc和free函数概述

2.1.1 malloc示例使用:

2.2 calloc函数概述

 2.2.1 calloc示例使用

2.3 realloc函数概述

2.3.1 realloc函数的示例使用

 2.4 动态内存开辟空间中的常见错误

三.常见笔试题

3.1 传参问题的笔试题

3.2 返回栈空间的地址的问题

3.3 造成内存泄漏问题



一.前言

我们之前编程时创建的一些变量,你知道它们都是存放在内存的哪里吗?

其实,不同的类型的变量在内存中存储的位置是不一样的。

一起来看一下:

C语言—动态内存分配相关知识详解

 那么为什么要有动态内存开辟这一说呢?

有时候我们需要的空间大小在程序运行的时候才能知道,那数组在编译时开辟空间的方式就不能满足了,这时候就需要我们的动态内存分配了。


动态内存开辟主要要求我们了解和掌握四个函数

1.malloc

2.calloc

3.realloc

4.free

二.动态内存函数详解及其使用

2.1 malloc和free函数概述

1. malloc函数:(文档地址:cplusplus.com)。 

C语言—动态内存分配相关知识详解

2. free函数 

C语言—动态内存分配相关知识详解

2.1.1 malloc示例使用:

#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<stdio.h>
int main()
{
    int* p = (int *)malloc(10 * sizeof(int));
    //如果开辟失败
    //一定要去检查
    if(p == NULL)
    {
        //打印错误原因
        printf("%s\n",strerror(errno));
    }
    else
    {
        //正常使用空间
        int i = 0;
        for(i = 0 ; i < 10 ; i++)
        {
            *(p+i) = i;
        }
        
        for(i = 0 ; i < 10 ; i++)
        {
            printf("%d\n",*(p+i));
        }
    }
    
    //当动态申请的空间不再使用的时候,就应该把空间还给操作系统
    free(p);//主动回收掉
    p = NULL;
    return 0;
}

剖析代码:

C语言—动态内存分配相关知识详解

如果,我将开辟的内存空间搞得很大,那么将会返回什么错误信息呢?

C语言—动态内存分配相关知识详解

其实操作系统是会在我们程序结束的时候,将动态内存开辟的空间释放掉的,那么free函数还有存在的必要吗?

当然!!

C语言—动态内存分配相关知识详解

C语言—动态内存分配相关知识详解

怎么样,到这里是不是对malloc和free函数的理解清楚了很多呢?


2.2 calloc函数概述

C语言—动态内存分配相关知识详解

 2.2.1 calloc示例使用

int main()
{
	int* p = calloc(10,sizeof(int));
    if(p == NULL)
    {
        //打印错误原因
        printf("%s\n",strerror(errno));
    }
    else
    {     
        int i = 0;
        for(i = 0 ; i < 10 ; i++)
        {
            printf("%d ",*(p+i));
        }
    }
    free(p);
    p = NULL;
}

代码剖析:

C语言—动态内存分配相关知识详解

 可以根据自己的实际需求来选择使用malloc函数还是calloc函数。


2.3 realloc函数概述

C语言—动态内存分配相关知识详解

 C语言—动态内存分配相关知识详解

2.3.1 realloc函数的示例使用


int main()
{
	int* p = (int *)malloc(5 * sizeof(int));

	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
	}

	else
	{
		int i = 0;
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i;
		}

		for (i = 0; i < 5; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	printf("\n");

	//这里我想在开辟20个空间给我使用

	int* p2 = (int *)realloc(p, 5* sizeof(int ));
	if(p2 != NULL)       //追加成功
	{
		p = p2;
	}

	int i = 0;

	for (i = 5; i < 10; i++)
	{
		*(p + i) = i;
	}

	for (i = 5; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	free(p);
	p = NULL;

	return 0;
}


代码剖析:

C语言—动态内存分配相关知识详解

思考一下:

C语言—动态内存分配相关知识详解

 C语言—动态内存分配相关知识详解


 2.4 动态内存开辟空间中的常见错误

1.对空指针进行解引用操作

这个错误不用多作介绍,空指针(NULL)当然是不能进行解引用操作的

 2.对动态开辟的内存越界访问

上端代码感受一下这个错误

int *p = (int *)malloc*(5 *sizoef(int));
if(p == NULL)
{
    return 0;
}
else
{
    for(int i = 0 ; i < 10 ; i++)
    {
        *(p+i) = i;
    }
    free(p);
    p=NULL;
}

 这里的错误很明显了,明明只开辟了五个空间,你缺要访问十个,有点过分呀~。

C语言—动态内存分配相关知识详解

 3.对非动态开辟的内存进行free操作

int main()
{
    int p = 10;
    free(p);
}

 p在这里不是动态开辟的,如果用free释放是会报错的。

4.对同一块儿动态内存多次释放。

三.常见笔试题

3.1 传参问题的笔试题

void GetMemory(char *p)
{
    p = (char *)malloc(100 *sizeof(int ));
}

void Test(void)
{
    char *str = NULL;
    GetMemory(str);
    strcpy(str,"Hello World!\n");
    printf(str);
   
}

int main()
{
    Test();
    return 0;
}

上面的这段代码会不会正确输出呢?

C语言—动态内存分配相关知识详解

很明显,这里没有输出“Hello World!”,

这段代码是有问题的。

那么问题出在哪里呢?

C语言—动态内存分配相关知识详解 

所以,这里也就很好的证明,为什么程序运行后没有输出。

那么怎么改正它呢? 

还记得嘛?传值不行的时候我们可以传址过去。

C语言—动态内存分配相关知识详解 

 C语言—动态内存分配相关知识详解

 成功运行

void GetMemory(char **p)
{
	*p = (char *)malloc(100 * sizeof(int));
}

void Test(void)
{
	char *str = NULL;
	GetMemory(&str);
	strcpy(str, "Hello World!\n");
	printf(str);

	free(str);
	str = NULL;
}

int main()
{
	Test();
	return 0;
}

大家记得把动态开辟的空间释放以及要把指针置空。

3.2 返回栈空间的地址的问题

char *GetMemory(void)
{
	char p[] = "hello world";
	return p;
}

void Test(void)
{
	char *str = NULL;
	str = GetMemory();
	printf(str);
}

int main()
{
	Test();

	return 0;
}

这段代码会顺利的打印“Hello World!”吗?

一起来看看。 

C语言—动态内存分配相关知识详解

我去,这是个什么玩意儿?为什么会打印出来这么个鬼东西?

别急,我们一起来看看吧 

C语言—动态内存分配相关知识详解

 所以,这里返回的东西我们没有人知道会是什么。

 

C语言—动态内存分配相关知识详解

 

3.3 造成内存泄漏问题

void Test(void)
{
	char *str = (char *)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	Test();
	return 0;
}

这段代码有没有问题呢?

C语言—动态内存分配相关知识详解

 正确的打印出来了。

但是,打印出来就没有问题了嘛?

C语言—动态内存分配相关知识详解

所以,我们写free函数之后,都要将这个指针顺便置为空(NULL)。以防止这种不规范的行为造成不可挽回的后果。


void Test(void)
{
	char *str = (char *)malloc(100);
	strcpy(str, "hello");
	free(str);
	str = NULL;
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	Test();
	return 0;
}

over~~~

上一篇:PuppeteerSharp Docker 中运行报错解决方案


下一篇:[BUUCTF-pwn] pwnable_secret_garden