C语言中如何进行内存管理

主页:17_Kevin-CSDN博客

收录专栏:《C语言》

C语言是一种强大而灵活的编程语言,但与其他高级语言不同,它要求程序员自己负责内存的管理。正确的内存管理对于程序的性能和稳定性至关重要。


一、引言

C 语言是一门广泛使用的编程语言,它为程序员提供了对内存的直接控制能力。这种对内存的控制使得 C 语言非常灵活,但也带来了更大的责任。在 C 语言中,程序员需要负责内存的分配和释放,否则可能会导致内存泄漏和其他内存管理问题。本文将深入探讨 C 语言的内存管理机制,包括内存分配、内存释放、内存泄漏等问题。

二、内存分配

C语言中有三种内存分配方式:

  • 静态内存分配
  • 栈内存分配
  • 动态内存分配

静态内存分配

静态内存分配:静态内存分配是在程序编译时进行的,它将内存分配给全局变量和静态变量。全局变量和静态变量的内存空间在程序运行期间一直存在,直到程序结束。静态内存分配的优点是内存分配和释放的效率高,缺点是内存使用不灵活,无法根据需要动态调整内存大小。

当我们创建变量的时候,系统将会自动的为变量分配空间:

//创建变量a
int a = 0;

可以观察到当创建变量a后系统会为a分配一块内存,这就是静态内存的分配。

栈内存的分配

栈内存分配是在程序运行时进行的,它将内存分配给函数内部的局部变量。栈内存的空间是有限的,当函数执行完毕后,栈内存会自动释放。栈内存分配的优点是内存管理简单,缺点是内存空间有限,不适合分配大内存。

例如:

当创建一个函数,在函数中创建一个变量local_num,和local_name

void test()
{int local_num = 17;char local_name = "Kevin";}int main()
{test();return 0;
}

 当调试时走过这两个局部变量但没有走出函数时可以观察到这两个变量成功的创建了:

 当走出函数后刷新即可发现两个变量变成了未标识变量:

这就是在函数中的栈内存分配,随用随分配,在用过后就销毁。

动态内存分配

动态内存分配是在程序运行时根据需要进行的内存分配。它使用 malloc() 函数或 calloc() 函数来分配内存空间,使用 free() 函数来释放内存空间。动态内存分配的优点是内存使用灵活,可以根据需要动态调整内存大小,缺点是内存管理复杂,容易出现内存泄漏等问题。

具体函数的使用可以翻阅博主这篇博客进行查阅

C/C++ (stdio.h)标准库详解-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/SDFsoul/article/details/135568683

1. malloc

malloc() 函数用于分配指定大小的内存块

int main() 
{int* ptr;// 分配 10 个整数的内存块ptr = (int*)malloc(10 * sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");exit(1);}// 访问分配的内存for (int i = 0; i < 10; i++) {ptr[i] = i + 1;}// 输出分配的内存中的值for (int i = 0; i < 10; i++) {printf("%d ", ptr[i]);}printf("\n");// 释放内存free(ptr);return 0;
}

在上述示例中,malloc() 函数用于分配 10 个整数的内存块。如果内存分配成功,ptr 将指向分配的内存块,否则输出错误信息并退出程序。然后,可以通过 ptr 访问和修改分配的内存。最后,使用 free() 函数释放分配的内存块。

2. calloc

calloc() 函数用于分配指定数量的元素,并将它们初始化为 0

#include <stdio.h>
#include <stdlib.h>int main() 
{int* ptr;// 分配 10 个整数的内存块,并将它们初始化为 0ptr = (int*)calloc(10, sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");exit(1);}// 访问分配的内存for (int i = 0; i < 10; i++) {printf("%d ", ptr[i]);}printf("\n");// 释放内存free(ptr);return 0;
}

在上述示例中,calloc() 函数用于分配 10 个整数的内存块,并将它们初始化为 0。如果内存分配成功,ptr 将指向分配的内存块,否则输出错误信息并退出程序。然后,可以通过 ptr 访问和修改分配的内存。最后,使用 free() 函数释放分配的内存块。

3. free

free() 函数用于释放之前分配的内存块,在上文malloc和calloc中均用到了free函数,目的就是在使用完分配的内存块后进行释放,避免内存泄漏。

三、内存释放

在 C 语言中,内存释放是非常重要的。如果忘记释放不再使用的内存,就会导致内存泄漏。内存泄漏会导致程序的性能下降,甚至可能导致程序崩溃。在 C 语言中,有两种常见的内存释放方式:手动释放和自动释放。

1. 手动释放

手动释放是指程序员使用 free() 函数来释放不再使用的内存空间。在使用动态内存分配时,程序员需要在不再使用内存空间时手动调用 free() 函数来释放内存。

#include <stdlib.h>int* allocate_memory(int size) 
{int* memory = (int*)malloc(size * sizeof(int));if (memory == NULL) {printf("内存分配失败\n");exit(1);}return memory;
}void free_memory(int* memory) 
{if (memory != NULL) {free(memory);}
}int main() 
{int* dynamic_memory = allocate_memory(10);for (int i = 0; i < 10; i++) {dynamic_memory[i] = i + 1;}for (int i = 0; i < 10; i++) {printf("%d ", dynamic_memory[i]);}printf("\n");free_memory(dynamic_memory);return 0;
}
  1. allocate_memory 函数用于动态分配一块大小为 size 个整数的内存空间,并返回指向该内存空间的指针。如果内存分配失败,程序会输出提示信息并调用 exit(1) 来退出程序。

  2. free_memory 函数用于释放动态分配的内存空间,首先检查指针是否为空,然后调用 free 函数进行内存释放。

  3. main 函数中,首先调用 allocate_memory 函数分配了包含 10 个整数的内存空间,并将返回的指针赋值给 dynamic_memory。然后使用循环给动态分配的内存赋值,并输出每个元素的值。

  4. 最后,通过调用 free_memory 函数释放动态分配的内存空间,避免内存泄漏。

2. 自动释放

自动释放是指在某些情况下,C 语言的编译器会自动释放不再使用的内存空间。例如,当函数执行完毕后,编译器会自动释放函数内部的栈内存。

#include <stdio.h>void function() 
{int local_variable = 30;printf("局部变量的值:%d\n", local_variable);
}int main() 
{function();return 0;
}

四、内存泄漏

内存泄漏指程序在不再需要使用内存时未将其释放,导致系统内存资源浪费。内存溢出则是指程序访问超出了已分配内存块的范围(例如数组越界访问)。


五、指针和内存

在C语言中,指针与内存密切相关。我们可以通过指针指向目标地址来直接操作内存,包括访问、修改和释放内存。

指针数组

int *ptrArray[10]; // 声明一个包含10个整型指针的数组

二级指针

int **pptr; // 声明一个二级整型指针
int value = 100;
int *ptr = &value;
pptr = &ptr; // 将ptr的地址赋给pptr

指针与结构体

结构体和指针的结合也是C语言中常见的用法,可以方便地操作复杂的数据结构(例如链表)。


希望这能帮助您更好地理解和应用C语言中的内存管理知识。

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

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

相关文章

VPX基于全国产飞腾FT-2000+/64核+复旦微FPGA的计算刀片

6U VPX计算板 产品简介 产品特点 飞腾计算平台&#xff0c;国产化率100% VPX-MPU6902是一款基于飞腾FT-2000/64核的计算刀片&#xff0c;主频2.2GHz&#xff0c;负责业务数据流的管控和调度。搭配自带独立显示芯片的飞腾X100芯片&#xff0c;可用于于各类终端及服务器类应用场…

蚓链数字化生态系统助力企业业务数字化转型

在当今数字化浪潮中&#xff0c;企业数字化转型已成为提升竞争力的关键。蚓链数字化生态系统致力于通过业务和技术的协同推动企业数字化转型&#xff0c;为企业提供了一套系统化的业务数字化解决方案。 业务数字化的第一步是根据企业当前业务分布&#xff0c;划分业务板块&…

spring boot整合cache使用memcached

之前讲了 spring boot 整合 cache 做 simple redis Ehcache 三种工具的缓存 上文 windows系统下载安装 memcached 我们装了memcached 但spring boot没有将它的整合纳入进来 那么 我们就要自己来处理客户端 java历史上 有过三种客户端 那么 我们用肯定是用最好的 Xmemcached …

Debian更改主机名重启失效怎么解决

要在Debian系统上更改主机名并使其生效&#xff0c;您可以按照以下步骤进行操作&#xff1a; 使用以下命令更改主机名&#xff1a; sudo hostnamectl set-hostname 新主机名 编辑 /etc/hosts 文件&#xff0c;将旧主机名替换为新主机名。您可以使用文本编辑器打开该文件进行编辑…

vue2 + axios + mock.js封装过程,包含mock.js获取数据时报404状态的解决记录,带图文,超详细!!!

vue axios mock.js 以下是封装的过程&#xff0c;记录一下 1、首先先了解什么是mock.js的用途及特点 官网地址&#xff1a;Mock.js (mockjs.com) 作用&#xff1a;生成随机数据&#xff0c;拦截 Ajax 请求 优势&#xff1a; 2、了解axios的原理及使用 官网地址&#xff1a…

Oracle之缓存融合

CACHE FUSION 原理 为了更深入的了解Oracle的后台进程的工作原理&#xff0c;需要先了解一下 RAC 中多节点对共享数据文件访问的管理是如何进行的。要了解 RAC 工作原理的中心&#xff0c;需要知道 Cache Fusion 这个重要的概念&#xff0c;要发挥 Cache Fusion 的作用&#xf…

大模型(LLM)的token学习记录-I

文章目录 基本概念什么是token?如何理解token的长度&#xff1f;使用openai tokenizer 观察token的相关信息open ai的模型 token的特点token如何映射到数值&#xff1f;token级操作&#xff1a;精确地操作文本token 设计的局限性 tokenizationtoken 数量对LLM 的影响训练模型参…

转转高效改表平台的演进之路

## 前言 我们假设这么一个场景&#xff0c;你管理着一个渡口&#xff0c;现在有一个人要过河&#xff0c;在没有桥的情况下&#xff0c;不管是早上晚上还是凌晨&#xff0c;你都要用船驮着他过河。随着时间的推移&#xff0c;越来越多的人过河。你会忙不过来&#xff0c;甚至崩…

研发日记,MatlabSimulink开箱报告(九)——Simulink Test模块

文章目录 前言 Simulink Test模块 静态测试 动态测试 逻辑测试 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;四&#xff09;——S-Fuction模块》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-F…

练习 2 Web [ACTF2020 新生赛]BackupFile 1

[ACTF2020 新生赛]BackupFile 1 Web常规题目 首先尝试查找常见的前端页面index.php之类的&#xff0c;没找到 题目有个“BackupFile”——备份文件 尝试用工具遍历查找相关的文件 御剑没扫出来&#xff0c;搜索搭建好dirsearch后&#xff0c;扫出来的index.php.bak 扫描工…

每天一个数据分析题(一百七十八)

在大样本&#xff08;样本量为n&#xff09;下进行某一列数据&#xff08;A列&#xff09;均值的区间估计时&#xff0c;假设点估计的值计算为a&#xff0c;显著性水平为0.05&#xff0c;z0.025为给定的显著性水平下的正态分布的临界值&#xff0c;则使用EXCEL的计算方法正确的…

GitCommandError: ‘reset --keep v2.41^0‘ on repo failed

1.背景 参考文章《AOSP代码清华镜像下载关键步骤-CSDN博客》于前一个多月通不过AOSP代码&#xff0c;现需要同步另外一个未曾同步的子仓库&#xff0c;例如&#xff1a;system/nfc. 在执行命令repo sync system/nfc时报标题错误。 A new version of repo is available GitCo…

迟到的VNCTF2024逆向题WP

这次比赛因为有事外出&#xff0c;只做了前两题&#xff0c;最近有空才把另外3题也做出来&#xff0c;总体来说比以往的VNCTF逆向题目要难一些。当然也有可能是我水平退步了&#xff0c;就算有时间参加比赛&#xff0c;应该也做不完这5题。VN的小伙伴越来越厉害了&#xff0c;出…

C#学习 part1 初窥C#

初窥C# C#简介&环境、安装C#程序结构C#基本语法参考 C#简介&环境、安装 C#是一个现代的、通用的、面向对象的编程语言。 其专为公共语言基础结构(CLI) 。CLI由可执行代码和运行时环境组成&#xff0c;允许在不同的计算机平台和体系结构上使用各种高级语言。 环境 C#是…

猜猜心里数字(个人学习笔记黑马学习)

1.定义一个变量&#xff0c;数字类型&#xff0c;内容随意 2.基于input语句输入猜想的数字&#xff0c;通过if和多次elif的组合&#xff0c;判断猜想数字是否和心里数字一致 num5if int(input("请输入第一次猜想的数字&#xff1a;"))5:print("猜对了&#xff0…

ROS 2基础概念#1:计算图(Compute Graph)| ROS 2学习笔记

在ROS中&#xff0c;计算图&#xff08;ROS Compute Graph&#xff09;是一个核心概念&#xff0c;它描述了ROS节点之间的数据流动和通信方式。它不仅仅是一个通信网络&#xff0c;它也反映了ROS设计哲学的核心——灵活性、模块化和可重用性。通过细致探讨计算图的高级特性和实…

Java中使用Jsoup实现网页内容爬取与Html内容解析并使用EasyExcel实现导出为Excel文件

场景 Pythont通过request以及BeautifulSoup爬取几千条情话&#xff1a; Pythont通过request以及BeautifulSoup爬取几千条情话_爬取情话-CSDN博客 Node-RED中使用html节点爬取HTML网页资料之爬取Node-RED的最新版本&#xff1a; Node-RED中使用html节点爬取HTML网页资料之爬…

远程服务器Ubuntu 18.04安装VNC远程桌面

一、安装vnc 1.安装图形化界面工具 # 安装过程中会弹窗让选择配置&#xff0c;选lightdm sudo apt install ubuntu-desktop sudo apt-get install gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal 2.安装vnc sudo apt-get install x11vnc3.安装LightD…

【LeetCode-674】最长连续递增序列(动归)

目录 LeetCode674.最长连续递增序列 题目描述 解法1&#xff1a;动态规划 代码实现 题目链接 题目描述 给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r&#xff08;l <…

ifcplusplus 示例 函数中英文 对照分析

有需求&#xff0c;需要分析 ifc c渲染&#xff0c;分析完&#xff0c;有 230个函数&#xff0c;才能完成一个加载&#xff0c;3d加载真的是大工程&#xff01; 函数中英文对照表&#xff0c;方便 日后开发&#xff0c;整理思路顺畅&#xff01;&#xff01;&#xff01;&#…