注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

WIN下的内存分配方式及相关概念  

2014-04-09 12:25:14|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

WIN下的内存分配方式及相关概念

Win32环境下,可以使用多种方式来分配/使用/释放动态内存,这些方式包括:

1. Win32 APIVirtualAlloc ()HeapAlloc ()LocalAlloc()GlobalAlloc()

2. Cmalloc()free()

3. C++newdelete

VirtualAlloc ()/VirtualFree()Windows系统提供的最"核心"的对虚拟内存操作的接口(或者是VirtualAllocEx()/VirtualFreeEx()),也是其他几种内存分配方式的基础,它是几种方式中最通用的,也是功能最强大的。VirtualAlloc()用来分配一定范围的虚拟页。VirtualAlloc一次分配1PAGE以上的RAM,每次分配都是PAGE的整数倍。

HeapAlloc()/HeapFree()/HeapDestroy()用来从堆中分配一定数量的空间,HeapAlloc分配的内存是不能移动的。

VirtualAlloc分配的内存是按页来对齐,HeapAlloc分配的内存按8字节对齐

VirtualAlloc函数主要用在大内存分配,HeapAlloc用在小内存分配,VirtualAlloc分配的内存可以不提交到物理内存或页文件中,只是虚拟地址空间里保留这个内存区域.

HeapAllocVirtualAlloc的包装用法.相当于在一大块内存里切一小块来用,所以这个HeapAlloc的速度肯定会比VirtualAlloc的速度要慢.

HeapAlloc之前得先HeapCreate创建进程堆,创建时可以先初始化保留内存中的一块,实际上都是VirutualAlloc的复杂包装应用,所以得以页为单位来对齐.

什么时候才要用到VirtualAlloc呢?

在没有C运行库可用的时候,要用VirtualAlloc来申请内存。另外,VirtualAlloc还可对申请的内存有许多的控制。

1、可以保留地址空间但不是及分配内存,在需要的时候再分配;

2、可以声明分配的内存不使用分页;

3、可以指定内存在尽可能高的地址上分配;

4、指定内存的读、写、执行属性和内存保护;

5、禁止所分配内存被高速缓存。

 

LocalAllocGlobalAllocWin16 API中遗留下来的两个函数,Win32 API为了保持兼容性才包含了这两个函数。这两个函数内部是通过HeapAlloc()的一系列函数来操作一个"特殊"Heap对象(进程的默认堆对象)。每一个进程在初始化的时候,都会创建一个默认的Heap对象,在进程结束的时候销毁这个默认的Heap对象。LocalAllocGblobalAlloc的区别仅表现在Win16环境下,在Win16环境下,内存的地址是通过段:段内偏移量来获取的,LocalAlloc()只能在同一段内分配内存,而GlobalAlloc可以跨越段边界访问内存。 Win32环境下内存访问不存在这样的限制,表现出相同的功能。由于HeapAlloc()的一系列函数完全可以实现他们两个的功能,所以在Win32下不推荐使用这两个函数。

malloc()free()是使用频率最高的两个函数他们是标准C库中的一部分,所以具有极高的移植性。在Windows平台下malloc()free()是通过调用HeapAlloc()的一系列函数实现的。C语言的标准内存分配函数:malloccallocreallocfree等。malloc(size)在内存的动态存储区中分配一块长度为“size”字节的连续区域,返回该区域的首地址。ccalloc(nsize)在内存的动态存储区中分配n块长度为“size”字节的连续区域,返回首地址。realloc(*ptrsize):将ptr内存大小增大到sizeFree(ptr):释放ptr所指向的一块内存空间。

newdeleteC++内置的关键词(keyword)。当C++编译器看到关键词new的时候,编译器会执行以下两个任务:1,在堆上动态分配必要的内存。这个任务是由编译器提供的一个全局函数void* ::operator new(size_t)来完成的。2,调用CMyClass的构造函数来初始化刚刚生成的对象。new的具体实现是通过调用malloc来分配内存的。

总之,VirtualAlloc分配的是虚拟内存,HeapAllocmallocnew分配的是物理内存,是在堆上分配的。mallocnew的作用相同,都是调用了HeapAlloc函数。LocalAllocGlobalAlloc最好不要再用。

另外,使用VirtualAlloc分配的指针在sse2优化时可以直接赋值,或者用_mm_malloc()16字节对齐,但后者稍微慢些。使用new分配的内存不一定是16字节对齐的。

在内存分配的过程中,NEW 一般是在分配失败时会产生一个异常bad_alloc,如下:

        try {

            int* p = new int[SIZE];

            // 其它代码

        } catch ( const bad_alloc& e ) {

            return -1;

        }

但是在老的编译器,如VC6中,可能没有支持这种处理,那么就和纯C一样,返回的是一个空指针。所以判断的方法就不能用这种方法了。

另外需要说明的是,在使用HeapAlloc函数前,必须先使用HeapCreate()这个函数创建一个辅助堆栈。其优势在于:

保护组件;更加有效的进行内存管理。进行本地访问。减少线程同步的开销。迅速释放,并减少内存碎片(因为你可以一次把整个辅助堆栈释放掉,你在这个上面所做的所有的大小内存操作就全没了)。

LPVOID second = HeapCreate(  HEAP_NO_SERIALIZE,

                                ONE_PAGE_SIZE,

                                m_dwWorkSpace);

LPVOID pData = HeapAlloc(  second,

                                    HEAP_ZERO_MEMORY,

                                    dwAllView);

这个简单也不简单啊。

  评论这张
 
阅读(731)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017