IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 动态内存的释放、内存泄漏、函数指针 -> 正文阅读

[C++知识库]动态内存的释放、内存泄漏、函数指针

1、

malloc:分配内存块

calloc:分配内存块,并且全部初始化为0

realloc:调用之前申请的内存块的大小,缩小内存块的时候,开头地址不变,其他不要的数据也不变,只是右边界线

2、动态开辟空间:

(1)int *p6 = (int*)realloc(0, 10 * sizeof(int) * 4)=/int *p6 = (int*)malloc(10 * sizeof(int) * 4);相当于malloc,重新找了一块空间,并没有释放之前的空间。

(2)p = (int*)realloc(p, 10 * sizeof(int) * 4);//有可能在其后边续,也有可能重新开辟一块空间。

(3)一般用malloc加for循环代替calloc。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>
int main()
int main()
{
	//动态开辟 10个空间 int
	int* p1 = (int*)malloc(10 * sizeof(int));
	assert(p1 != NULL);//断言
	if (p1 == NULL)
	{
		return 0;
	}
	//动态开辟 20个空间 short
	short* p2 = (short*)malloc(20 * sizeof(short));
	assert(p2 != NULL);//断言
	if (p2 == NULL)
	{
		return 0;
	}
	//动态开辟 100个空间 double
	double* p3 = (double*)malloc(100 * sizeof(double));
	assert(p3 != NULL);//断言
	if (p3 == NULL)
	{
		return 0;
	}
	//动态开辟 30个空间 int 初始化为0
	int* p4 = (int*)calloc(30, sizeof(int));
	assert(p4 != NULL);//断言
	if (p4 == NULL)
	{
		return 0;
	}
	//动态开辟 50个空间 char 初始化为'A'
	char* p5 = (char*)calloc(50, sizeof(char));
	assert(p5 != NULL);//断言
	if (p5 == NULL)
	{
		return 0;
	}
	for (int i = 0; i < 50; i++)
	{
		p5[i] = 'A';
	}
	//对p进行扩容,扩容为40个空间
	p1 = (int*)realloc(p1, 10 * sizeof(int) * 4);//有可能在其后边续,也有可能重新开辟一块空间
    //int *p1 = (int*)realloc(0, 10 * sizeof(int) * 4)=/int *p1 = (int*)malloc(10 * sizeof(int) * 4);//相当于malloc,重新找了一块空间,并没有释放之前的空间
	assert(p1 != NULL);//断言
	if (p1 == NULL)
	{
		return 0;
	}
    //对p1进行缩小,缩小为5个
	p1 = (int*)realloc(p1, 5 * sizeof(int));
	assert(p1 != NULL);//断言
	if (p1 == NULL)
	{
		return 0;
	}
	return 0;

}

3、free函数

(1)C语言中有两个危险的东西:

? ? ? ?(a)数组越界

? ? ? ?(b)内存泄漏

? ? ? ? ?内存泄漏或内存碎片怎么处理:可以进行重启

(2)?void free(void *p),释放指针变量p所指向的动态内存;

(3)free函数的必要性:如果动态内存开辟,使用结束后没有释放,会导致申请的这块内存没有人可以使用,一般将这块没有人能使用的内存叫做垃圾,留着垃圾的函数会导致内存泄漏。

(4)使用malloc时,一个malloc搭配一个free

int main()
{
	/*
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	int* q = (int*)malloc(10 * sizeof(int));//申请q
	p = q;//让其相等,p指向q,p原先的内存空间没有释放,其他人都不能访问,p也不能访问,造成内存泄漏
	*/
	//改正
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	int* q = (int*)malloc(10 * sizeof(int));//申请q
	free(p);
	p = q;//让其相等,p指向q,p原先的内存空间没有释放,其他人都不能访问,p也不能访问,造成内存泄漏
	free(q);
}

(5)free函数报错的原因:

? ? ?(a)同一块内存连续释放;

? ? ?(b)free释放内存块A,但其参数并不是A的开始地址

int main()
{
	/*  报错,free释放内存块p,但其参数并不是p的开始地址
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	printf("%p\n", p);
	p++;
	printf("%p\n", p);//p指向第二个地址
	free(p);
	*/
	//改正
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	int* q =p;//备份,防止释放的不是p的开始地址
	printf("%p\n", p);
	p++;
	printf("%p\n", p);//p指向第二个地址
	free(q);
	free(p);
}

? ? ?(c)free释放后,会造成一个悬空指针

? ? ? ? 悬空指针:野指针,会造成不可知的错误,一般来说

? ? ? ? 空指针:指向0地址的指针,非NULL即真

? ? ? ?一般来说,free函数执行结束后会将其执行为NULL

int main()
{
	/*报错,连续释放p
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	free(p);
	free(p);
	*/
	//改正
	int* p = (int*)malloc(10 * sizeof(int));//申请p
	free(p);
	p = NULL;//修改为空
	free(p);//free传入空指针直接退出
}

4、函数指针:本质是一个指针,只是指针指向一个函数,编译器在编译期间对函数开辟了一块空间,而这块空间的开始地址就是函数开始地址。

? ? ? ? ?C标准规定,函数名是其开始地址,所以用指针p获取函数地址? p = &Max? ? 或? ? p = Max

函数指针p怎么调用:int tmp = (*p)(10, 20);//(*p)需要提高优先级
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tmp=p(10,20)也可以

int Max(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int(*p)(int, int);
	p = &Max;//p = Max取地址和不去地址一样
	int tmp = (*p)(10, 20);//(*p)需要提高优先级
	//tmp=p(10,20)也可以
	printf("%d\n", tmp);
}

5、编写简单计算器利用函数指针

int Add(int a, int b)
{
	return a + b;
}
int Sub(int a, int b)
{
	return a-b;
}
int Mul(int a, int b)
{
	return a* b;
}
int Div(int a, int b)
{
	if (b == 0)
	{
		return -1;
	}
	else
	{
		return a / b;
	}
}
int Computer(int a, int b, int(*p)(int, int))
{
	return p(a, b);
}
int main()
{
	printf("a+b=%d\n", Computer(10, 20, Add));
	printf("a-b=%d\n", Computer(10, 20, Sub));
	printf("a*b=%d\n", Computer(10, 20, Mul));
	printf("a/b=%d\n", Computer(10, 20,Div));
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-19 17:27:06  更:2021-11-19 17:28:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:55:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码