内存管理相关知识点 及 malloc 与 free
2010-07-06 18:06
267 查看
物理内存和虚拟内存
要理解内存在程序中是如何分配的,首先需要理解如何将内存从操作系统分配给程序。计算机上的每一个进程都认为自己可以访问所有的物理内存。显然,由于同时在运行多个程序,所以每个进程不可能拥有全部内存。实际上,这些进程使用的是
虚拟内存
。
只是作为一个例子,让我们假定您的程序正在访问地址为 629 的内存。不过,虚拟内存系统不需要将其存储在位置为 629 的 RAM
中。实际上,它甚至可以不在 RAM 中 —— 如果物理 RAM 已经满了,它甚至
可能已经被转移到硬盘上!由于这类地址不必反映内存所在的物理位置,所以它们被称为虚拟内存。操作系统维持着一个虚拟地址到物理地址的转换的表,以便计算
机硬件可以正确地响应地址请求。并且,如果地址在硬盘上而不是在 RAM
中,那么操作系统将暂时停止您的进程,将其他内存转存到硬盘中,从硬盘上加载被请求的内存,
然后再重新启动您的进程。这样,每个进程都获得了自己可以使用的地址空间,可以访问比您物理上安装的内存更多的内存。
在 32-位 x86 系统上,每一个进程可以访问 4 GB 内存
。现在,大部分人的系统上并没有 4 GB 内存,
即使您将 swap 也算上,
每个进程
所使用的内存也肯定少于 4 GB。因此,当加载一个进程时,
它会得到一个取决于某个称为
系统中断点(system break)
的特定地址的初始内存分配。该地址之后是未被映射的内存 —— 用于在 RAM 或者硬盘中没有分配相应物理位置的内存。因此,如果一个进程运行超出了
它初始分配的内存,那么它必须请求操作系统“映射进来(map in)”更多的内存。(映射是一个表示一一对应关系的数学术语 —— 当内存的虚拟地址有一个对应的物理地址来存储内存内容时,该内存将被映射。)
复制内容到剪贴板
代码:
这样可以计算free内存的大小
深入理解malloc 与 free
在malloc时带了size, free的时候却没有带,那么它回收的时候,怎么知道它的大小呢?
在malloc的时候, 会分配一个管理节点.
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize; // dbgheap.c 389行
其中_CrtMemBlockHeader 是一个32个字节的结构体.
nSize 为你malloc时带的大小.
nNoMansLandSize 的大小为4.
那么blockSize 整个空间的结构如下:
其中 real_data
为nSize大小的实际有效的存储空间, gap和end 为实际存储空间的栅栏,固定为0xFD,
界定在存储空间的一头一尾, 在回收的时候,会检查实际存储空间的一头一尾是否为0xFD,
如果不是, 可能该空间被写越界了, 就不能正常回收了.
blockSize 空间的初始化代码如下:
pHead->pBlockHeaderNext = _pFirstBlock; // dbgheap.c 431行
pHead->pBlockHeaderPrev = NULL;
pHead->szFileName = (char *)szFileName;
pHead->nLine = nLine;
pHead->nDataSize = nSize; // 记录 malloc的大小
pHead->nBlockUse = nBlockUse;
pHead->lRequest = lRequest;
/* link blocks together */
_pFirstBlock = pHead;
/* fill in gap before and after real block */
memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize); // 四个字节,固定为0xFD
memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize); // 四个字节,固定为0xFD
/* fill data with silly value (but non-zero) */
memset((void *)pbData(pHead), _bCleanLandFill, nSize); // 初始化malloc空间, 设为0xCD
static unsigned char _bNoMansLandFill = 0xFD; /* fill no-man's land with this */
static unsigned char _bDeadLandFill = 0xDD; /* fill free objects with this */
static unsigned char _bCleanLandFill = 0xCD; /* fill new objects with this */
static unsigned char _bAlignLandFill = 0xBD; /* fill no-man's land for aligned routines */
在VC2003下测试获得分配空间的大小:
#include <stdio.h>
int get_malloc_size(void * buff)
{
int size = 0;
unsigned char *p = (unsigned char*)buff - 16;
size = *p++;
size |= *p++ << 8;
size |= *p++ << 16;
size |= *p++ << 24;
return size;
}
int main(int argc, char *argv[])
{
unsigned char *buff;
int size = 0;
buff = (unsigned char *)malloc(1024);
size = get_malloc_size(buff); // 获得刚刚分配的空间大小
free(buff);
return 0;
}
要理解内存在程序中是如何分配的,首先需要理解如何将内存从操作系统分配给程序。计算机上的每一个进程都认为自己可以访问所有的物理内存。显然,由于同时在运行多个程序,所以每个进程不可能拥有全部内存。实际上,这些进程使用的是
虚拟内存
。
只是作为一个例子,让我们假定您的程序正在访问地址为 629 的内存。不过,虚拟内存系统不需要将其存储在位置为 629 的 RAM
中。实际上,它甚至可以不在 RAM 中 —— 如果物理 RAM 已经满了,它甚至
可能已经被转移到硬盘上!由于这类地址不必反映内存所在的物理位置,所以它们被称为虚拟内存。操作系统维持着一个虚拟地址到物理地址的转换的表,以便计算
机硬件可以正确地响应地址请求。并且,如果地址在硬盘上而不是在 RAM
中,那么操作系统将暂时停止您的进程,将其他内存转存到硬盘中,从硬盘上加载被请求的内存,
然后再重新启动您的进程。这样,每个进程都获得了自己可以使用的地址空间,可以访问比您物理上安装的内存更多的内存。
在 32-位 x86 系统上,每一个进程可以访问 4 GB 内存
。现在,大部分人的系统上并没有 4 GB 内存,
即使您将 swap 也算上,
每个进程
所使用的内存也肯定少于 4 GB。因此,当加载一个进程时,
它会得到一个取决于某个称为
系统中断点(system break)
的特定地址的初始内存分配。该地址之后是未被映射的内存 —— 用于在 RAM 或者硬盘中没有分配相应物理位置的内存。因此,如果一个进程运行超出了
它初始分配的内存,那么它必须请求操作系统“映射进来(map in)”更多的内存。(映射是一个表示一一对应关系的数学术语 —— 当内存的虚拟地址有一个对应的物理地址来存储内存内容时,该内存将被映射。)
内存管理基本技术之:块头
代码:void myfree(void* p) { void* pointer = (char*)p – sizeof(Header); return free(pointer); }
复制内容到剪贴板
代码:
typedef unsigned long Header; void* mymalloc (size_t size) { void* mem = malloc(size + sizeof(Header)); *((Header*)mem) = size; return (char*)mem + sizeof(Header); }
这样可以计算free内存的大小
深入理解malloc 与 free
在malloc时带了size, free的时候却没有带,那么它回收的时候,怎么知道它的大小呢?
在malloc的时候, 会分配一个管理节点.
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize; // dbgheap.c 389行
其中_CrtMemBlockHeader 是一个32个字节的结构体.
nSize 为你malloc时带的大小.
nNoMansLandSize 的大小为4.
那么blockSize 整个空间的结构如下:
pBlockHeaderNext | pBlockHeaderPrev | szFileName | nLine | nSize | nBlockUse | lRequest | gap | real_data | end |
为nSize大小的实际有效的存储空间, gap和end 为实际存储空间的栅栏,固定为0xFD,
界定在存储空间的一头一尾, 在回收的时候,会检查实际存储空间的一头一尾是否为0xFD,
如果不是, 可能该空间被写越界了, 就不能正常回收了.
blockSize 空间的初始化代码如下:
pHead->pBlockHeaderNext = _pFirstBlock; // dbgheap.c 431行
pHead->pBlockHeaderPrev = NULL;
pHead->szFileName = (char *)szFileName;
pHead->nLine = nLine;
pHead->nDataSize = nSize; // 记录 malloc的大小
pHead->nBlockUse = nBlockUse;
pHead->lRequest = lRequest;
/* link blocks together */
_pFirstBlock = pHead;
/* fill in gap before and after real block */
memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize); // 四个字节,固定为0xFD
memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize); // 四个字节,固定为0xFD
/* fill data with silly value (but non-zero) */
memset((void *)pbData(pHead), _bCleanLandFill, nSize); // 初始化malloc空间, 设为0xCD
static unsigned char _bNoMansLandFill = 0xFD; /* fill no-man's land with this */
static unsigned char _bDeadLandFill = 0xDD; /* fill free objects with this */
static unsigned char _bCleanLandFill = 0xCD; /* fill new objects with this */
static unsigned char _bAlignLandFill = 0xBD; /* fill no-man's land for aligned routines */
在VC2003下测试获得分配空间的大小:
#include <stdio.h>
int get_malloc_size(void * buff)
{
int size = 0;
unsigned char *p = (unsigned char*)buff - 16;
size = *p++;
size |= *p++ << 8;
size |= *p++ << 16;
size |= *p++ << 24;
return size;
}
int main(int argc, char *argv[])
{
unsigned char *buff;
int size = 0;
buff = (unsigned char *)malloc(1024);
size = get_malloc_size(buff); // 获得刚刚分配的空间大小
free(buff);
return 0;
}
相关文章推荐
- 内存管理(C语言中malloc和free的用法)
- 内存管理中的(new、delete、malloc、free)
- C语言内存管理:malloc、calloc、free的实现
- 【C语言】malloc()和free()函数的讲解以及相关内存泄漏问题
- 内存管理:new/delete操作符与malloc()/free()函数
- 内存管理: malloc()与free()的一种基于clib标准的实现
- c++ 内存管理:7、有了malloc/free为什么还要new/delete?
- C语言内存管理:malloc、calloc、free的实现
- Linux C 动态内存分配--malloc,new,free及相关内容
- C++ 内存管理之四(new/delete vs malloc/free)
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
- (转)内存管理(C语言中malloc和free的用法)
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
- 环境表 内存管理-malloc()/free()
- Linux C 动态内存分配--malloc,new,free及相关内容
- malloc()和free()函数的讲解以及相关内存泄漏问题
- 内存管理: malloc()与free()的一种基于池表结构的实现
- 内存管理——关于malloc/free与new/delete
- malloc()和free()的相关知识