内存中堆的基本概念

一、什么是堆?

C语言堆是由malloc(),calloc(),realloc()等函数动态获取内存的一种机制。使用完成后,由程序员调用free()等函数进行释放。使用时,需要包含stdlib.h头文件。

C++预言的堆管理则是使用new操作符向堆管理器申请动态内存分配,使用delete操作符将使用完毕内存的释放给堆管理器。

 

要动态管理一片内存,且需要动态分配释放,这样一个需求。很显然C语言需要将动态内存区抽象描述起来并实现动态管理。事实上,C语言中堆管理器其本质是利用数据结构将堆区抽象描述,所需要描述的方面:

  • 可用于分配的内存
  • 正在使用的内存块
  • 释放掉的内存块

再利用相应算法对于这类数据结构对象进行动态管理而实现的堆管理器。

经常看到各种算法书很多只讲算法原理,而不讲应用实例,往往体会不深。私以为可以做些改善。学而不能致用,何必费力去学。所以不是晦涩难懂的算法无用,而是没有去真正结合应用。可以再进一步想,如果算法没有应用场景,也一定会在技术发展的历程中逐渐被世人遗忘。所以建议学习阅读算法书籍时,找些实例来看看,一定会加深对算法的理解领悟。这是比较重要的题外话,送给大家以共勉。

所以从本质上讲,堆管理器就是数据结构+算法实现的动态内存管理器,管理内存的动态分配以及释放。

二、为什么要用堆?

 C编程语言对内存管理方式有静态,自动或动态三种方式。静态内存分配的变量通常与程序的可执行代码一起分配在主存储器中,并在程序的整个生命周期内有效。自动分配内存的变量在栈上分配,并随着函数的调用和返回而申请或释放。对于静态分配内存和自动分配内存的生命周期,分配的大小必须是编译时常量(可变长度自动数组[5]除外)。如果所需的内存大小直到运行时才知道(例如,如果要从用户或磁盘文件中读取任意大小的数据),则使用固定大小的数据对象则满足不了要求了。试想,即便假定都知道要多大内存,如在windows/Linux下有那么多应用程序,每个应用程序加载时都将运行中所需的内存采样静态分配策略,则如多个程序运行内存将很快耗尽。

分配的内存的生命周期也可能引起关注。静态或自动分配都不能满足所有情况。自动分配内存不能在多个函数调用之间保留,而静态数据在程序的整个生命周期中必然保留,无论是否真正需要(所以都采用这样的策略必然造成浪费)。在许多情况下,程序员在管理分配的内存的生命周期具有更多的灵活性。

通过使用动态内存分配则避免了这些限制/缺点,在动态内存分配中,更明确(但更灵活)地管理内存,通常是通过从免费存储区(非正式地称为“堆”)中分配内存(为此目的而构造的内存区域)进行分配的。在C语言中,库函数malloc用于在堆上分配一个内存块。程序通过malloc返回的指针访问该内存块。当不再需要内存时,会将指针传递给free,从而释放内存,以便可以将其用于其他目的。

堆可实现动态内存管理的多样性,在牺牲一定开销情况下(申请/释放开销,以及内存开销),可以提供内存的利用率,在一定程度上解决内存不足的需求。

三、谁实现堆?

如果一问到这个问题,马上会说C编译器。不错C编译器实现了堆管理器,而事实上并非编译器在编译的过程中实现动态内存管理器,而是C编译器所实现的C库实现了堆管理器,比如ANSI C,VC, IAR C编译器,GNU C等其实都需要一些C库的支持,那么这些库的内部就隐藏了这么一个堆管理器。操作系统内核也可能实现堆管理器。

四、堆使用常见错误

  • 使用前没有检查分配失败:内存分配不能保证成功,而是可能返回一个空指针。使用返回的值,而不检查分配是否成功,将调用未定义的行为。这通常会导致崩溃,但不能保证会发生崩溃,因此依赖于它而不检查结果也会导致问题。
  • 内存泄露:使用free释放内存失败会导致不可重用内存的累积,程序不再使用这些内存。这将浪费内存资源,并可能在耗尽这些资源时导致分配失败。
  • 逻辑错误:所有的分配必须遵循相同的模式:使用malloc分配,使用free释放,重新分配。如果不能坚持这种模式,例如在调用free(悬空指针)之后或在调用malloc(野指针)之前使用内存、调用free两次(“double free”)等,通常会导致分段错误并导致程序崩溃。这些错误可能是偶发的,而且很难调试。

免责声明:转载文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除 

Linux内存管理是一种复杂且功能强大的技术,它基于一系列算法和策略来有效地使用和管理系统的内存资源。以下是Linux内存管理的基本概念: 1. 分页和段管理:Linux采用分页机制来管理物理内存,它将内存划分为固定大小的页或帧。同时,它还采用分段机制来管理进程的虚拟地址空间,将进程的地址空间划分为一系列段(如代码段、数据段和段)。 2. 内存映射:Linux使用内存映射来将文件或设备直接映射到内存中,这样可以直接访问文件内容或设备寄存器,而无需进行系统调用或访问文件系统。 3. 交换和回收:当系统内存不足时,Linux使用交换机制将不再活跃的进程或数据页从内存中移除,并将其存储在交换空间(也称为交换分区)中。当需要更多内存时,可以从交换空间中恢复这些页面。回收机制则用于回收不再需要的内存页面,以供其他进程使用。 4. 缓存:Linux使用缓存来提高内存使用效率。缓存通常包括页替换缓存(用于存储不再使用的页面)和缓存数据结构(如TLB,用于加速虚拟到物理的转换)。 5. 动态内存分配:Linux提供了多种动态内存分配机制,如brk()和sbrk()系统调用来调整的大小,mmap()系统调用用于映射文件或创建新的内存区域。 6. 内存使用和监控:Linux提供了多种工具和接口来监控和管理系统的内存使用情况,如free、top、vmstat等命令,以及/proc文件系统中的信息。 总的来说,Linux的内存管理策略旨在实现高效的内存使用、动态调整、缓存优化和故障恢复等功能,以确保系统在各种负载和场景下的稳定运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值