1.malloc申请的空间,是否记录空间大小?若是记录,那所记录的空间大小在哪呢?为什么利用free释放不需要空间大小参数呢?

malloc申请空间时,记录其空间大小(其空间上方,有一个数据头,头部信息就记录了申请空间的大小),当调用free函数时,即需要读取头部信息得到需要释放的字节数

malloc申请的空间,一 申请的内存 小的靠近数据区 ,大的靠近栈区,而中间的是“无人区””

malloc工作在user space(用户态),是以什么样的数据结构组织从内核中申请分配一大块内存?
内核态(资源都是由OS管理的)和用户态交互(调用系统API open、close、read、write )
malloc第一次向内核申请(申请堆内存的系统API)brk()(增加或减小brk指针相当于申请和回退申请的内存)和mmap()(将磁盘上的页面加载到虚拟地址空间上) 申请的单位是页面,申请后返回申请整个内存的起始地址,然后将用户申请的多少字节返回给用户,其他空间由malloc函数库(用户态)来管理,此后用户申请的小内存不需要要向OS申请。
malloc(0)也会申请内存资源
malloc(-10) 拒接不做任何处理

int *p = (int *)malloc(sizeof(int) * 10);
if(NULL==p)exit(1);//malloc申请之后,一定要记得检测其是否申请成功(为了多线程安全)!

申请空间时,为其分配了40个字节的空间作为数据空间(即用户需要的),还分配了8个字节的越界标记,这个应该和栈的carray技术一样,检查越界的,所以发生越界错误时,是在free时才会检测出来错误,free也只是在调用free时才发现才去即时制止。同时还会分配头部空间的字节,来记录malloc分配的空间大小20字节 40+8+20=40+28,即系统还会多提供32字节的内存(头部空间大小不,一般int 20 char 24)

free的越界标记是针对于malloc函数库的,标记位是面向系统的。

同时free其实进行了堆空闲块的合并

2.malloc函数的相关堆分配算法


在这种情况中**,一个块是由一个字的头部、有效载荷,以及可能的一些额外的填充组成的。头部编码了这个块的大小(包括头部和所有的填充),以及这个块是已分配的还是空闲的。如果我们强加一个双字的对齐约束条件**,那么块大小就总是8的倍数,且块大小的最低3位总是零。因此,我们只需要内存大小的29个高位,释放剩余的3位来编码其他信息。在这种情况中,我们用其中的最低位(已分配位)来指明这个块是已分配的还是空闲的。例如,假设我们有一个已分配的块,大小24(0x18)字节。那么它的头部将是
0x00000018 l 0x1 = 0x00000019
类似地,一个块大小为40(Ox28)字节的空闲块有如下的头部:
0x00000028 I 0x0 = 0x00000028
头部后面就是应用调用malloc时请求的有效载荷。有效载荷后面是一片不使用的填充块,其大小可以是任意的。需要填充有很多原因。比如,填充可能是分配器策略的一部分,用来对付外部碎片。或者也需要用它来满足对齐要求。

隐式空闲链表

我们称这种结构为隐式空闲链表,是因为空闲块是通过头部中的大小字段隐含地连接着的。分配器可以通过遍历堆中所有的块,从而间接地遍历整个空闲块的集合。注意,我们需要某种特殊标记的结束块,在这个示例中,就是一个设置了已分配位而大小为零的终止头部(ter-minating header)。
隐式空闲链表的优点是简单。显著的缺点是任何操作的开销,例如放置分配的块,要求对空闲链表进行搜索,该搜索所需时间与堆中已分配块和空闲块的总数呈线性关系。
很重要的一点就是意识到系统对齐要求和分配器对块格式的选择会对分配器上的最小块大小有强制的要求。没有已分配块或者空闲块可以比这个最小值还小。例如,如果我们假设一个双字的对齐要求,那么每个块的大小都必须是双字(8字节)的倍数。因此,图9-35中的块格式就导致最小的块大小为两个字:一个字作头,另一个字维持对齐要求。即使应用只请求一字节,分配器也仍然需要创建一个两字的块。

3.malloc申请失败,即可使用的内存满时应该怎么办?

#include <stdlib.h>
#include <pthread.h>struct foo {int            f_count;pthread_mutex_t    f_lock;/* more stuff here */
};struct foo *
foo_alloc(void)    /* allocate the object */
{struct foo *fp;if((fp = malloc(sizeof(struct foo))) != NULL){fp->f_count = 1;if(pthread_mutex_init(&fp->f_clock, NULL) != 0){free(fp);return(NULL);}    /* continue initialization */}return(fp);
}void
foo_hold(struct foo *fp) /* add a reference to the object */
{pthread_mutex_lock(&fp->f_clock);fp->f_count++;pthread_mutex_unlock(&fp->f_lock);
}void
foo_rele(struct foo *fp) /* release a reference to the object */
{pthread_mutex_lock(&fp->f_lock);if(--fp->f_count == 0)    /* last reference */{pthread_mutex_unlock(&fp->f_lock);pthread_mutex_destroy(&fp->f_lock);free(fp);}else{pthread_mutex_unlock(&fp->f_lock);}
}

对于多个对象利用堆区时。
在使用该对象前,线程需要对这个对象的引用计数加1,当对象使用完毕时,需要对引用计数减1。当最后一个引用被释放时,对象所占的内存空间就被释放。在对引用计数加1、减1以及检查引用计数是否为0这些操作之前需要锁住互斥量。

当堆内存满时,可以利用虚拟内存来进行。

虚拟内存(计算机系统内存管理)(cache和主存构成了系统的内存,而主存和辅存依靠辅助软硬件的支持构成了虚拟存储器。 )

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。

虚拟内存别称虚拟存储器(Virtual Memory)。电脑中所运行的
程序均需经由内存执行,若执行的程序占用内存很大或很多,则会导致内存消耗殆尽。为解决该问题,Windows中运用了虚拟内存技术,即匀出一部分硬盘空间来充当内存使用。当内存耗尽时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。若计算机运行程序或操作所需的随机存储器(RAM)不足时,则 Windows 会用虚拟存储器进行补偿。它将计算机的RAM和硬盘上的临时空间组合。当RAM运行速率缓慢时,它便将数据从RAM移动到称为“分页文件”的空间中。将数据移入分页文件可释放RAM,以便完成工作。 一般而言,计算机的RAM容量越大,程序运行得越快。若计算机的速率由于RAM可用空间匮乏而减缓,则可尝试通过增加虚拟内存来进行补偿。但是,计算机从RAM读取数据的速率要比从硬盘读取数据的速率快,因而扩增RAM容量(可加内存条)是最佳选择。

工作原理

虚拟存储器是由硬件和操作系统自动实现存储信息调度和管理的。它的工作过程包括6个步骤:
①中央处理器访问主存的逻辑地址分解成组号a和组内地址b,并对组号a进行地址变换,即将逻辑组号a作为索引,查地址变换表,以确定该组信息是否存放在主存内。
②如该组号已在主存内,则转而执行④;如果该组号不在主存内,则检查主存中是否有空闲区,如果没有,便将某个暂时不用的组调出送往辅存,以便将这组信息调入主存。
③从辅存读出所要的组,并送到主存空闲区,然后将那个空闲的物理组号a和逻辑组号a登录在地址变换表中。
④从地址变换表读出与逻辑组号a对应的物理组号a。 [
⑤从物理组号a和组内字节地址b得到物理地址。
⑥根据物理地址从主存中存取必要的信息。

https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98/101812?fr=aladdin

1 内存泄露是什么意思?

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。(程序还在运行,没有退出。)
内存泄漏缺陷具有隐蔽性、积累性的特征,比其他内存非法访问错误更难检测。因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。

2 哪些常见行为会导致内存泄露?

内存泄露不是简单的没有进行delete和free
1.丢失地址
2.运行的堆空间满了,就将所有的内存空间都申请完了,无法执行了,系统甚至崩溃(系统无法回写数据),且此时内存空间无法释放?
3.对象没有析构,直接调用free进行释放?是因为标记位没有处理吗? 没有虚函数时可以偷懒直接进行空间对对象的赋值吗?

3 造成的内存泄露程序结束时,内存会释放吗?

操作系统回收资源是指,当程序(进程)结束后,程序所使用的资源都会被操作系统回收。但是如果程序一直在运行的话, 如果你不主动释放空间的话,用new申请的空间是不会被回收的。此时将标记位改变。

4.对堆内存的管理

1.堆内存申请释放,利用线程,一个线程来统计其空间被多少线程使用,另一个线程判断其空间没人使用则释放,需要读写锁。

2.堆内存申请释放,利用继承机制,父类来申请空间,子类使用空间,子类析构,父类释放空间(利用栈机制,但一般理解子类对象为构造时,先对父类构造,再对子类构造,析构时,先对子类析构,再对父类释放) 即父类和子类的责任分离,一个负责申请释放,一个负责使用析构。

malloc申请堆内存相关推荐

  1. 【C++】内存管理到用new申请堆内存

    目录 前言 一.C/C++中程序内存区域划分 二.C++使用new申请堆内存 1.new和delete的使用 2.new和delete的底层实现 前言 hello~❥(ゝω・✿ฺ) 大家好呀!欢迎能够 ...

  2. linux 用户进程结束后 malloc申请的内存会自动释放吗,进程退出后malloc的内存是否会被释放?

    当一个进程退出后,不管是正常退出或者是异常退出,操作系统都会释放这个进程的资源.包括这个进程分配的内存,打开的文件等等. 内存泄露的前提是进程一直在运行:进程一旦退出,所占的整个虚拟内存都被销毁,所有 ...

  3. linux下malloc申请大内存,Linux malloc大内存的方法

    ---------------------------------------------------------------------------------------------------- ...

  4. C++ 在一个类中用指针的形式申请堆内存构造出另一个类并访问私有成员变量(包括智能指针版本)

    一.普通指针版本 代码 #include<iostream> using namespace std;class A {public:A(){ax=2;cout<<" ...

  5. malloc申请内存问题

    问题描述 最近发现了一个越界有概率会造成段错误的问题.具体问题是这样的,首先malloc申请一块内存,但使用时比实际的大一个字节,比如我申请了52个字节,使用了53个或者申请50个使用了51个,然后我 ...

  6. 间接通过new 来申请一个二维的堆内存数组

    我们知道无法直接通过new 来申请一个二维的堆内存数组,于是有人想出了这样一个办法:创建一个一维堆内存指针数组,即每个数组元素是一个指针,然后用new 给各个指针分配一个一维的堆内存数组,那么最后表示 ...

  7. malloc申请内存空间失败

    上午在调试自己写的一段代码的过程中,发现malloc函数分配内存失败,仔细梳理了一下自己写的代码,失败的malloc操作之前也malloc了两三次,但都是成功的,网上搜了一下,都提到失败的原因可能是因 ...

  8. Linux堆内存管理深入分析(上)

    Linux堆内存管理深入分析 (上半部) 作者:走位@阿里聚安全   0 前言 近年来,漏洞挖掘越来越火,各种漏洞挖掘.利用的分析文章层出不穷.从大方向来看,主要有基于栈溢出的漏洞利用和基于堆溢出的漏 ...

  9. 栈和堆存储在计算机RAM中,堆内存和栈内存及C++内存分配

    1.现代操作系统内存管理主流的操作系统(Windows,Linux)都采用虚拟内存管理的方式,具体说就是:页式管理.段式管理.段页式管理. 操作系统分配资源的单位是进程,所以,内存管理的过程也是以进程 ...

最新文章

  1. vb.net 功能f8键事件_Excel中F1~F12所有功能键作用,你知道吗?
  2. springboot配置html资源路径,SpringBoot普通.html文件视图配置
  3. python词云改颜色_使用Python创建一个与图像颜色匹配的词云
  4. Stanford机器学习笔记-1.线性回归
  5. .Net 2.0中使用扩展方法
  6. IOS基础之计算器的编写
  7. 只用一套解决方案,就可解决80%的交通物流行业信息难题
  8. (剑指Offer)面试题55:字符流中第一个不重复的字符
  9. PyQt4 的事件与信号 -- 发射信号
  10. 瑞士科学家造出了撞不坏的无人机丨Science Robitics
  11. OutputDebugString输出调试信息
  12. 基础练习: 使用openssl命令创建RSA密钥
  13. Java基础之数组练习
  14. php curl 超时 返回空,PHP curl 返回Connection timed out解决办法
  15. JAVA学子商城项目问题集锦(springboot)
  16. 28.XAPP1052驱动详解-WinDriver DMA读写流程
  17. cassandra vs. voldemort
  18. linux发音,你发对了吗
  19. 转载:数学工具常见问题集
  20. Apple公司的官方声明

热门文章

  1. CCF-小明上学(C语言)
  2. vnpy量化回测怎么做?一文带你了解
  3. 6 MySQL 集群Cluster
  4. 图解IFRS9 金融工具(13)实施时间及结语 [
  5. hashmap!hashmap
  6. clock oscillator,generator,buffer选型杂谈
  7. FFMPEG - 视频解码器
  8. 如何用python编写问卷调查_如何通过Python实现自动填写调查问卷
  9. 联想小新pad安装Google Play教程
  10. CSS3实现实时时间数字滚动