当前位置: 首页 > news >正文

C语言基础系列【20】内存管理

博主介绍:程序喵大人

  • 35- 资深C/C++/Rust/Android/iOS客户端开发
  • 10年大厂工作经验
  • 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
  • 《C++20高级编程》《C++23高级编程》等多本书籍著译者
  • 更多原创精品文章,首发gzh,见文末
  • 👇👇记得订阅专栏,以防走丢👇👇
    😃C++基础系列专栏
    😃C语言基础系列
    😃C++大佬养成攻略

在C++编程中,内存管理是一个至关重要的概念。

要深入理解内存管理,我们肯定要了解堆内存和栈内存的基本概念、区别以及它们的动态分配和释放方法。还需要深入理解相关内存分配函数malloccallocrealloc的用法。

基本概念理解

栈内存

栈内存是由编译器自动管理的内存区域,用于存储局部变量、函数参数和返回地址等。栈内存的分配和释放是自动进行的:

  • 当函数被调用时,局部变量和参数会被压入栈中;
  • 当函数返回时,这些局部变量和参数会被弹出栈并释放。

栈内存具有快速分配和释放的特点,但其大小是固定的,一般也就8M左右,不能动态调整。

堆内存

堆内存是由程序员手动管理的内存区域,用于动态分配内存。

你通过malloccallocrealloc等函数可以在堆上分配内存,通过free函数释放内存。

堆内存的大小不固定,可以动态调整,但需要程序员负责内存的管理,容易出现内存泄漏等问题,我们常说的内存泄露问题指的更多的就是堆内存的泄露。

区别

  • 内存****管理:栈内存由编译器自动管理,堆内存由程序员手动管理。
  • 作用域:栈内存的作用域通常是函数内部,当函数返回时,栈内存会自动被释放;堆内存的作用域由程序员控制,只要程序员不释放,内存就会一直存在。
  • 生命周期:栈内存的生命周期与函数执行时间相关,函数执行完毕后,栈内存会被释放;堆内存的生命周期由程序员控制,直到显式调用free函数释放内存。

堆内存的使用

使用malloc动态分配空间

malloc函数用于在堆上分配指定大小的内存块。函数声明形式为:

void* malloc(size_t size);
  • size:要分配的字节数。
  • 返回值:指向分配的内存块的指针,如果分配失败,返回NULL

示例代码:

int* ptr = (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存空间
if (ptr == NULL) {// 处理内存分配失败的情况
}

使用calloc分配并初始化内存

calloc函数用于在堆上分配内存并初始化为0。函数声明形式为:

void* calloc(size_t num, size_t size);
  • num:要分配的元素个数。
  • size:每个元素的字节数。
  • 返回值:指向分配的内存块的指针,如果分配失败,返回NULL

示例代码:

int* ptr = (int*)calloc(10, sizeof(int)); // 分配10个int类型的内存空间,并初始化为0
if (ptr == NULL) {// 处理内存分配失败的情况
}

使用realloc调整内存大小

realloc函数用于调整已分配内存块的大小。函数声明形式为:

void* realloc(void* ptr, size_t size);
  • ptr:指向要调整大小的内存块的指针。
  • size:新的内存块大小(字节数)。
  • 返回值:指向新的内存块的指针,如果分配失败,返回NULL,原内存块保持不变。

示例代码:

int* ptr = (int*)malloc(sizeof(int) * 10); // 初始分配10个int类型的内存空间
if (ptr == NULL) {// 处理内存分配失败的情况
}// 使用realloc调整内存大小
ptr = (int*)realloc(ptr, sizeof(int) * 20);
if (ptr == NULL) {// 处理内存调整失败的情况,注意原内存块仍然有效
}

使用free释放内存

free函数用于释放之前通过malloccallocrealloc分配的内存空间。函数声明形式为:

void free(void* ptr);
  • ptr:指向要释放的内存块的指针。

示例代码:

int* ptr = (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存空间
if (ptr == NULL) {// 处理内存分配失败的情况
}// 使用内存...free(ptr); // 释放内存
ptr = NULL; // 将指针置为NULL,避免悬挂指针

栈内存与堆内存的对比

编程实践展示

以下示例展示了栈内存和堆内存的不同使用场景和特性:

#include <stdio.h>
#include <stdlib.h>void stackMemoryExample() {int stackVar = 10; // 栈内存,函数返回时自动释放printf("Stack variable: %d\n", stackVar);
}void heapMemoryExample() {int* heapVar = (int*)malloc(sizeof(int)); // 堆内存,需要手动释放if (heapVar == NULL) {fprintf(stderr, "Memory allocation failed\n");return;}*heapVar = 20;printf("Heap variable: %d\n", *heapVar);free(heapVar); // 释放堆内存heapVar = NULL; // 避免悬挂指针
}int main() {stackMemoryExample(); // 调用栈内存示例函数heapMemoryExample();  // 调用堆内存示例函数return 0;
}

其中

stackMemoryExample函数使用了栈内存来存储局部变量stackVar,当函数返回时,stackVar会自动释放。

heapMemoryExample函数则使用堆内存来存储变量heapVar,并通过malloc分配内存,通过free释放内存。

练习

  1. 编写一个程序,动态分配一个整型数组的内存空间,用于存储用户输入的5个整数,然后遍历并打印这些整数。最后,释放分配的内存。
  2. 编写一个程序,包含两个函数。第一个函数使用栈内存(局部变量)存储并打印一个整数数组;第二个函数使用堆内存动态分配并存储用户输入的整数数组,然后打印并释放内存。通过这两个函数的调用,展示栈内存和堆内存在使用上的区别。

进阶

  1. 为什么malloc时候需要传递长度信息,而free时候却不需要传递长度信息呢?会不会多释放一些内存或者少释放了一些内存?
  2. malloc更底层的原理是什么?一次malloc底层都经历了什么?
  3. 栈内存和堆内存的区别?
  4. 什么场景下使用栈,什么场景下使用堆呢?
  5. 栈数组下标越界访问会发生什么?
  6. 什么是栈溢出?
  7. 了解下常见的栈攻击手段。

码字不易,欢迎大家点赞关注评论,谢谢!


C++训练营

专为校招、社招3年工作经验的同学打造的1V1 C++训练营,量身定制学习计划、每日代码review,简历优化,面试辅导,已帮助多名学员获得offer!训练营介绍

相关文章:

C语言基础系列【20】内存管理

博主介绍&#xff1a;程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章&#xff0c;首发gzh&#xff0c;见文末&#x1f447;&#x1f…...

JavaScript基础-递增和递减运算符

在JavaScript编程中&#xff0c;递增&#xff08;&#xff09;和递减&#xff08;--&#xff09;运算符是用于对数值进行加一或减一操作的基础工具。它们简洁且强大&#xff0c;但如果不正确地使用&#xff0c;可能会导致混淆或错误。本文将详细介绍这两种运算符的不同形式及其…...

计算机毕业设计SpringBoot+Vue.js社区医疗综合服务平台(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

3.6c语言

#define _CRT_SECURE_NO_WARNINGS #include <math.h> #include <stdio.h> int main() {int sum 0,i,j;for (j 1; j < 1000; j){sum 0;for (i 1; i < j; i){if (j % i 0){sum i;} }if (sum j){printf("%d是完数\n", j);}}return 0; }#de…...

Unity开发——CanvasGroup组件介绍和应用

CanvasGroup是Unity中用于控制UI的透明度、交互性和渲染顺序的组件。 一、常用属性的解释 1、alpha&#xff1a;控制UI的透明度 类型&#xff1a;float&#xff0c;0.0 ~1.0&#xff0c; 其中 0.0 完全透明&#xff0c;1.0 完全不透明。 通过调整alpha值可以实现UI的淡入淡…...

深度学习驱动的跨行业智能化革命:技术突破与实践创新

第一章 深度学习的技术范式演进与核心架构 1.1 从传统机器学习到深度神经网络的跨越 深度学习的核心在于通过多层次非线性变换自动提取数据特征,其发展历程可划分为三个阶段:符号主义时代的规则驱动(1950s-1980s)、连接主义时代的浅层网络(1990s-2000s)以及深度学习时代…...

php配置虚拟主机

在PHP中配置虚拟主机&#xff0c;通常是通过Apache或Nginx等Web服务器来进行设置的。下面我将分别介绍如何在Apache和Nginx中配置PHP虚拟主机。 1. Apache 配置虚拟主机 Apache是最常用的Web服务器之一&#xff0c;配置虚拟主机的步骤如下&#xff1a; 步骤一&#xff1a;确保A…...

RESTful API 设计指南

RESTful API 介绍 大佬的总结&#xff1a;RESTful API 设计指南 - 阮一峰的网络日志 json-server github地址 这里介绍一个快速搭建 REST API 服务的工具包 接口测试工具 介绍几个接口测试工具 apipost apifox postman https://www.apipost.cn/ (中文) https://www.apifox…...

在虚拟机上安装Hadoop

以下是在虚拟机上安装Hadoop的一般步骤&#xff1a; 准备工作 - 安装虚拟机软件&#xff1a;如VMware Workstation或VirtualBox等。 - 创建虚拟机&#xff1a;选择合适的操作系统镜像&#xff0c;如Ubuntu或CentOS等Linux发行版&#xff0c;为虚拟机分配足够的CPU、内存和磁盘…...

大白话JavaScript实现一个函数,将字符串中的每个单词首字母大写。

大白话JavaScript实现一个函数&#xff0c;将字符串中的每个单词首字母大写。 答题思路 理解需求&#xff1a;要写一个函数&#xff0c;它能接收一个字符串&#xff0c;然后把这个字符串里每个单词的第一个字母变成大写。分解步骤 拆分单词&#xff1a;一般单词之间是用空格隔…...

【VUE2】第三期——样式冲突、组件通信、异步更新

目录 1 scoped解决样式冲突 2 data写法 3 组件通信 3.1 父子关系 3.1.1 父向子传值 props 3.1.2 子向父传值 $emit 3.2 非父子关系 3.2.1 event bus 事件总线 3.2.2 跨层级共享数据 provide&inject 4 props 4.1 介绍 4.2 props校验完整写法 5 v-model原理 …...

深度学习代码解读——自用

代码来自&#xff1a;GitHub - ChuHan89/WSSS-Tissue 借助了一些人工智能 2_generate_PM.py 功能总结 该代码用于 生成弱监督语义分割&#xff08;WSSS&#xff09;所需的伪掩码&#xff08;Pseudo-Masks&#xff09;&#xff0c;是 Stage2 训练的前置步骤。其核心流程为&a…...

Linux 配置静态 IP

一、简介 在 Linux CentOS 系统中默认动态分配 IP 地址&#xff0c;每次启动虚拟机服务都是不一样的 IP&#xff0c;因此要配置静态 IP 地址避免每次都发生变化&#xff0c;下面将介绍配置静态 IP 的详细步骤。 首先先理解一下动态 IP 和静态 IP 的概念&#xff1a; 动态 IP…...

Oxidized收集H3C交换机网络配置报错,not matching configured prompt (?-mix:^(<CD>)$)

背景&#xff1a;问题如上标题&#xff0c;H3C所有交换机配置的model都是comware 解决方案&#xff1a; 1、找到compare.rb [rootoxidized model]# pwd /usr/local/lib/ruby/gems/3.1.0/gems/oxidized-0.29.1/lib/oxidized/model [rootoxidized model]# ll comware.rb -rw-r--…...

RAG技术深度解析:从基础Agent到复杂推理Deep Search的架构实践

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…...

6.过拟合处理:确保模型泛化能力的实践指南——大模型开发深度学习理论基础

在深度学习开发中&#xff0c;过拟合是一个常见且具有挑战性的问题。当模型在训练集上表现优秀&#xff0c;但在测试集或新数据上性能大幅下降时&#xff0c;就说明模型“记住”了训练数据中的噪声而非学习到泛化规律。本文将从实际开发角度系统讲解如何应对过拟合&#xff0c;…...

【玩转23种Java设计模式】结构型模式篇:组合模式

软件设计模式&#xff08;Design pattern&#xff09;&#xff0c;又称设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 汇总目录链接&…...

专业工具,提供多种磁盘分区方案

随着时间的推移&#xff0c;电脑的磁盘空间往往会越来越紧张&#xff0c;许多人都经历过磁盘空间不足的困扰。虽然通过清理垃圾文件可以获得一定的改善&#xff0c;但随着文件和软件的增多&#xff0c;磁盘空间仍然可能显得捉襟见肘。在这种情况下&#xff0c;将其他磁盘的闲置…...

SELinux 概述

SELinux 概述 概念 SELinux&#xff08;Security-Enhanced Linux&#xff09;是美国国家安全局在 Linux 开源社区的帮助下开发的一个强制访问控制&#xff08;MAC&#xff0c;Mandatory Access Control&#xff09;的安全子系统。它确保服务进程仅能访问它们应有的资源。 例…...

【十三】Golang 通道

&#x1f4a2;欢迎来到张胤尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 通道通道声明初始化缓冲机制无缓冲通道代码示例 带…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...