C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等的介绍

文章目录

  • 前言
  • 一、为什么存在动态内存管理
  • 二、动态内存函数的介绍
    • 1. malloc函数
    • 2. 内存泄漏
    • 3. 动态内存开辟位置
    • 4. free函数
    • 5. calloc 函数
    • 6. realloc 函数
    • 7. realloc 传空指针
  • 总结


前言

C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等的介绍

一、为什么存在动态内存管理

int a = 0;
int arr[5] = {0};
  • 上述的开辟空间的方式有两个特点:
  1. 空间开辟大小是固定的。
  2. 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
    但是对于空间的的需求,不仅仅是上述的情况
    有时候,我们需要的空间大小在程序运行的时候才能知道,上述的编译时开辟空间的方式就不能满足了。
    这时候就只能用动态内存开辟了。

二、动态内存函数的介绍

1. malloc函数

  • malloc 函数需要引入头文件 <stdlib.h>
    C语言提供了一个动态内存开辟的函数:
void* malloc(size_t size);

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

  • 如果开辟成功,则返回一个指向开辟好空间的指针
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定
  • size 指的是 size字节 的大小的空间
  • 如果参数 size 为 0, malloc 的行为是标准未定义的,取决于编译器
  1. 动态开辟40个字节大小的空间
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{int arr[10] = { 0 };int* p = (int*)malloc(40); // malloc 开辟 40 个字节大小的内存空间// 检验如果 动态内存开辟失败,打印错误信息,终止程序if (NULL == p){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf("%d ", *(p + i)); // 0 1 2 3 4 5 6 7 8 9}return 0;
}
  1. 需要开辟的内存空间过大返回空指针
    INT_MAX 是定义的一个 21亿多的一个数字
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{int arr[10] = { 0 };int* p = (int*)malloc(INT_MAX * 2); // malloc 开辟 INT_MAX * 2 个字节大小的内存空间// 检验如果 动态内存开辟失败,打印错误信息,终止程序if (NULL == p){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf("%d ", *(p + i)); // Not enough space}return 0;
}

2. 内存泄漏

  1. 如果一个程序在向内存申请空间后,没有释放申请的空间,则在程序结束的时候,系统会自动回收内存空间
  2. 如果一个程序在向内存申请空间后,没有释放申请的空间, 并且程序在持续运行,短时间不结束,此时就存在内存泄漏

3. 动态内存开辟位置

  • 动态内存开辟在堆区
  • 局部变量等开辟在栈区
    在这里插入图片描述

4. free函数

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

void free (void* ptr);

free 函数是用来释放动态开辟的内存。

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的 行为是未定义的。
  • 如果参数 ptr 是 NULL 指针,则函数什么事都不做。
  • malloc 和 free 函数都声明在 <stdlib.h>头文件中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{int arr[10] = { 0 };int* p = (int*)malloc(40); // malloc 开辟 40 个字节大小的内存空间// 检验如果 动态内存开辟失败,打印错误信息,终止程序if (NULL == p){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf("%d ", *(p + i)); // 0 1 2 3 4 5 6 7 8 9}free(p);p = NULL;return 0;
}
  • free (p) 就会 将申请40个字节的动态内存空间 释放掉。
  • 但是 p 依然存放着 之前接收的动态内存的地址,会变成野指针。
  • 所以 在 释放完p 的空间后 将p 重置为 NULL指针。

5. calloc 函数

C语言还提供另外一个叫 calloc,calloc,函数也用来动态内存分配。

void* calloc(size_t num, size_t size);
  • 函数功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0
  • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
  • 需要初始化时,用 calloc, 不需要初始化 用 malloc。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{int* p = (int*)calloc(10, sizeof(int)); // 开辟 10 个 int类型大小 的空间if (NULL == p){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){// 自动初始化为全 0printf("%d ", *(p + i)); // 0 0 0 0 0 0 0 0 0 0 }free(p);p = NULL;return 0;
}

6. realloc 函数

  • realloc 函数的出现让动态内存管理更加灵活
  • realloc函数可以做到对动态开辟内存大小的调整
void* realloc(void* ptr, size_t size);
  • ptr 是要调整的内存地址
  • size 调整之后新大小
  • 返回值为调整之后的内存起始位置
  • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
  • realloc在调整内存空间的时候存在两种情况:
    • 1: 原有空间之后有足够大的空间。
    • 2: 原有空间之后的空间不够或被占用。

在这里插入图片描述


#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{int* p = (int*)malloc(40); // 开辟 10 个 int类型大小 的空间if (NULL == p){printf("%s\n", strerror(errno));return 1;}int i = 0;// 使用for (i = 0; i < 10; i++){*(p + i) = i + 1;}// 扩容int* str = (int*)realloc(p, 80);if (str != NULL){p = str;}// 使用for (i = 10; i < 20; i++){*(p + i) = i + 1;}for (i = 0; i < 20; i++){printf("%d ", *(p + i)); // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}free(p);p = NULL;return 0;
}

7. realloc 传空指针

  • realloc传空指针 和 malloc是等价的。
#include <stdio.h>
int main()
{int* p = realloc(NULL, 40);// 此时 realloc 和 malloc(40)是等价的return 0;
}

总结

C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等的介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/7185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript this 上下文深度探索:综合指南涵盖隐式与显式call、apply、bind、箭头函数、构造函数等用法于多样场景

JavaScript中的this关键字代表函数执行的上下文环境&#xff0c;核心在于确定函数内部访问的当前对象。它根据函数调用方式动态变化&#xff0c;对事件处理、对象方法调用等至关重要。通过.call(), .apply(), .bind()或箭头函数控制this&#xff0c;可确保代码逻辑正确绑定对象…

ROS 2边学边练(43)-- 利用GTest写一个基本测试(C++)

前言 在ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;gtest&#xff08;Google Test&#xff09;是一个广泛使用的C测试框架&#xff0c;用于编写和执行单元测试。这些测试可以验证ROS节点、服务和消息等的正确性和性能。 如果我们需要在写的包中添加测试&…

[redis] redis为什么快

1. Redis与Memcached的区别 两者都是非关系型内存键值数据库&#xff0c;现在公司一般都是用 Redis 来实现缓存&#xff0c;而且 Redis 自身也越来越强大了&#xff01;Redis 与 Memcached 主要有以下不同&#xff1a; (1) memcached所有的值均是简单的字符串&#xff0c;red…

被安排了一个任务,执行过程中要注意什么?

1 少来“把信带给加西亚”那一套。一朝领命去&#xff0c;几年百折不挠&#xff0c;和组织失去联系也要把事儿办成的故事虽然很励志&#xff0c;但并不是真相。真相是组织的目标和打法都在快速变化&#xff0c;只有和他人保持密切互动&#xff0c;才能在变化中达成目标。 2 不…

Web自动化-PO模式

目标 深入理解方法封装的思想能够使用方法封装的思想对代码进行优化深入理解PO模式的思想熟练掌握PO模式的分层思想 PO模式学习思路 采用版本迭代的方式来学习&#xff0c;便于对不同版本的优缺点进行对比和理解。 V1&#xff1a;不使用任何设计模式和单元测试框架V2&#xf…

保持 Hiti 证卡打印机清洁的重要性和推荐的清洁用品

在证卡印刷业务中&#xff0c;保持印刷设备的清洁至关重要。特别是对于 Hiti 证卡打印机来说&#xff0c;它们是生产高质量证卡的关键工具。保持设备清洁不仅可以保证打印质量和效率&#xff0c;还可以延长其使用寿命。本文将探讨保持 Hiti 证卡打印机清洁卡的重要性&#xff0…

Linux中对文件的操作(一)

linux中对文件进行操作 open函数 *int open(const char pathname, int flags); pathname&#xff1a;指的是文件名 flags&#xff1a;权限 只读打开O_RDONLY 只写打开O_WRONLY 可读可写打开O_RDWR 以上三个参数中应当只指定一个。 #include <sys/types.h> #include &l…

首届云原生编程挑战赛总决赛亚军比赛攻略(ONE PIECE团队)

关联比赛: 首届云原生编程挑战赛【复赛】实现一个 Serverless 计算服务调度系统 比赛攻略—ONE PIECE团队 代码链接&#xff1a; 初赛&#xff1a;GitHub - czy-gm/containerScheduler: 2020天池首届云原生编程挑战赛亚军-初赛赛道二&#xff08;实现规模化容器静态布局和动…

高项-案例分析万能答案(作业分享)

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 一、通用问题原因: 1.项目经理管理经验不足&#xff0c;没有及时发现和解决xx方面的问题。 2.项目管理计划没有得到关键干系人的评审确…

yum常用命令与lrzsz的在线安装

yum命令 yum&#xff08; Yellow dog Updater, Modified&#xff09;是一个在 Fedora 和 RedHat 以及 SUSE 中的 Shell 前端软件包管理器。 基于 RPM 包管理&#xff0c;能够从指定的服务器自动下载 RPM 包并且安装&#xff0c;可以自动处理依赖性关系&#xff0c;并且一次安装…

php基础知识快速入门

一、PHP基本知识 1、php介绍&#xff1a; php是一种创建动态交互性的强有力的服务器脚本语言&#xff0c;PHP是开源免费的&#xff0c;并且使用广泛。PHP是解释性语言&#xff0c;按顺序从上往下执行&#xff0c;无需编译&#xff0c;直接运行。PHP脚本在服务器上运行。 2、ph…

动态规划(dp)(二)

按摩师 按摩师 1.状态表示 dp【i】表示&#xff1a;到i位置时&#xff0c;此时最长时长 继续细化&#xff1a;在i位置选预约&#xff0c;或不选预约 f【i】&#xff1a;到i位置时&#xff0c;nums【i】必选的&#xff0c;最长时长 g【i】&#xff1a;到i位置时&#xff0c…

仅为娱乐,Python中如何重定义True为False?

在Python中&#xff0c;True 和 False 是内建的布尔常量&#xff0c;分别代表逻辑上的真和假。它们是不可变的&#xff0c;且在Python语言规范中具有特殊地位&#xff0c;不能被用户直接重定义。尝试给 True 或 False 赋予新的值是违反Python语言规则的&#xff0c;这样的操作会…

刷题记录4.17-5.6

文章目录 刷题记录27.移除元素977.有序数组的平方209.长度最小的子数组707.设计链表206.反转链表24.两两交换链表中的节点19.删除链表的倒数第N个节点142.环形链表II242.有效的字母异位词349.两个数组的交集454.四数相加II18.四数之和151.反转字符串中的单词459.重复的子字符串…

Educational Codeforces Round 165 (Rated for Div. 2) E. Unique Array 贪心+线段树

Unique Array 题目描述 给你一个长度为 n n n 的整数数组 a a a 。 a a a 的子数组是其连续的子序列之一&#xff08;即数组 [ a l , a l 1 , … , a r ] [a_l, a_{l1}, \dots, a_r] [al​,al1​,…,ar​] 中的某个整数 l l l 和 r r r 的子数组 1 ≤ l < r ≤ n …

如何检查 MIDI 文件的安全性

检查 MIDI 文件的安全性通常涉及几个步骤&#xff0c;因为 MIDI 文件本身并不包含可执行代码&#xff0c;所以它们不是传统意义上的恶意软件载体。然而&#xff0c;它们仍然可能以间接的方式带来安全风险&#xff0c;例如通过诱导用户下载与 MIDI 文件一起提供的恶意附件或链接…

JS基础:变量的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃&#xff0c;大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端基础路线”&#xff0c;可获取…

Leetcode181_超过经理收入的员工

1.leetcode原题链接:. - 力扣&#xff08;LeetCode&#xff09; 2.题目描述 表&#xff1a;Employee ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | salary | int | | manage…

零基础入门学习Python第二阶01生成式(推导式),数据结构

Python语言进阶 重要知识点 生成式&#xff08;推导式&#xff09;的用法 prices {AAPL: 191.88,GOOG: 1186.96,IBM: 149.24,ORCL: 48.44,ACN: 166.89,FB: 208.09,SYMC: 21.29}# 用股票价格大于100元的股票构造一个新的字典prices2 {key: value for key, value in prices.i…

病毒及网络攻击(信息安全)

一、病毒 计算机病毒的特征&#xff1a;传播性、隐蔽性、感染性、潜伏性、触发性、破坏性等 Worm -- 蠕虫病毒 Trojan -- 特洛伊木马 Backdoor -- 后门病毒 Macro -- 宏病毒 宏病毒 感染的对象主要是 文本文档、电子表格等 木马病毒&#xff1a;冰河 蠕虫病毒&#xff1a;欢乐时…