查找了一些 new , GlobalAlloc, HeapAlloc分配内存方式的区别。
转了一些资料
//===========================================================//
下面是资料1:
1. GlobalAlloc函数和new()的区别。
1>new是标准的C++分配内存函数。GlobalAlloc是WIN下的API函数。
2>new分配内存同时会调用类等对象的构造函数。GlobalAlloc不回。
3>new分配的内存只能同进程使用,如(A进程new,B进程不能delete),GlobalAlloc能多进程使用,并删除。
2. GlobalAlloc分配的内存需要释放么?
所有动态内存分配都必须释放,GlobalAlloc分配的内存用GlobalFree进行释放。
3. GlobalAlloc和HeapAlloc的关系
GlobalAlloc
是win16留下来的函数,它调用HeapAlloc分配堆中的内存。在理想的win32环境下,我们不需要GlobalAlloc,但是实际上,我们还
得保留从win16移植过来的许多代码。在这些代码中使用了“内存句柄”(HGLOBAL)参数而不是32位的内存地址。
GlobalAlloc
根据其属性参数做两件不同的事情。如果参数指定了GMEM_FIXED,则GlobalAlloc简单调用HeapAlloc,把返回地址作为一个32位
HGLOBAL值;如果参数指定了GMEM_MOVEABLE,则返回的HGLOBAL值是一个指向进程里句柄表中某一项入口的指针,该入口包含指向实际
HeapAlloc分配的内存的指针。
从本质上,如果我们不调用GlobalReAlloc函数,我们就可以用HeapAlloc代替GlobalAlloc。
//==================///
下面是资料2:
GlobalAlloc是标准内存管理函数,标准内存管理函数都是操作进程的默认堆,所以这个函数是从进程的从进程的默认堆中分配内存空间,分配的空间可以是可移动的也可以是不可以移动的。可移动的内存是指windows在需要的时候可以将这个内存移动到另外一个地址
HeapAllock
是堆管理函数,堆管理函数可以操作非默认堆(当然也可以操作默认堆),创建一个堆是用HeapCreate,这个函数返回一个堆句柄,然后可以用在
HeapAllock函数中,即从返回的这个堆中申请内存空间,HeapAllock申请的内存只能是不可以移动的
而new则是c++的标准函数,在windows的vc++编译器中,new在申请内存最终调用的是GlabalAllock,不过new还会调用类的构造函数。
windows的内存管理除了标准内存管理函数和堆管理函数之外,还有更加底层的虚拟内存管理函数,VirtualAllock就是一个虚拟内存管理函数。
//======================================================//
下面是资料3: 来自:http://blog.csdn.net/jianxiong8814/article/details/1560288
关于更多内容,如果你英语还可以的话,建议不阅读一下内容,直接进入以下链接
http://msdn2.microsoft.com/en-us/library/aa366723.aspx
malloc()与 alloc()
C语言跟内存分配方式(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等.其中alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间.calloc则将初始化这部分的内存,设置为0. 而realloc则对malloc申请的内存进行大小的
调整.申请的内存最终需要通过函数free来释放. 而sbrk则是增加数据段的大小;
malloc/calloc/free基本上都是C函数库实现的,跟OS无关.C函数库内部通过一定的结构来保存当前有多少可用内存.如果程序malloc的大小超出了库里所留存的空间,那么将首先调用brk系统调用来增加可用空间,然后再分配空间.free时,释放的内存并不立即返回给os,而是保留在内部结构中. 可以打个比方: brk类似于批发,一次性的向OS申请大的内存,而malloc等函数则类似于零售,满足程序运行时的要求.这套机制类似于缓冲.使用这套机制的原因: 系统调用不能支持任意大小的内存分配(有的系统调用只支持固定大小以及其倍数的内存申请,这样的话,对于小内存的分配会造成浪费; 系统调用申请内存代价昂贵,涉及到用户态和核心态的转换.
函数malloc()和calloc()都可以用来分配动态内存空间,但两者稍有区别。 malloc()函数有一个参数,即要分配的内存空间的大小: Void *malloc(size_t size); calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小: void *calloc(size_t numElements,size_t sizeOfElement); 如果调用成功,函数malloc()和calloc()都将返回所分配的内存空间的首地址。
malloc() 函数和calloc()函数的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没
有被使用过,则其中的每一位可能都是0;反之,如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,使用
malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题。
calloc() 函数会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初
始化为零;如果你是为指针类型的元素分配内存,那么这些元素通常(但无法保证)会被初始化为空指针;如果你是为实数类型的元素分配内存,那么这些元素可能
(只在某些计算机中)会被初始化为浮点型的零。
malloc() 函数和calloc()函数的另一点区别是calloc()函数会返回一个由某种对象组成的数组,但malloc()函数只返回一个对
象。为了明确是为一个数组分配内存空间,有些程序员会选用calloc()函数。但是,除了是否初始化所分配的内存空间这一点之外,绝大多数程序员认
为以下两种函数调用方式没有区别: calloc(numElements ,sizeOfElement); malloc(numElements *sizeOfElement) ; 需要解释的一点是,理论上(按照ANSIC标准)指针的算术运算只能在一
个指定的数组中进行,但是在实践中,即使C编译程序或翻译器遵循这种规定,许多C程序还是冲破了这种限制。因此,尽管malloc()函数并不能返回一个
数组,它所分配的内存空间仍然能供一个数组使用(对realloc()函数来说同样如此,尽管它也不能返回一个数组)。 总之,当你在calloc()函数和malloc()函数之间作选择时,你只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。 当程序运行过程中malloc了,但是没有free的话,会造成内存泄漏.一部分的内存没有被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内存,是的系统可用内存不断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回
收所有的资源.因此,适当的重起一下程序,有时候还是有点作用.
=====================================================
用GlobalAlloc函数来分配内存
GlobalAlloc函数接受两个参数。第一个是一个标志,指定几种分配方式中的一种。
GMEM_FIXED = 0x0000分配固定内存.
GMEM_MOVEABLE = 0x0002分配可移动内存.
GMEM_ZEROINIT = 0x0040初始化内存内容,为0.
GPTR = 0x0040 Combines GMEM_FIXED and GMEM_ZEROINIT.
GHND = 0x0042 Combines GMEM_MOVEABLE and GMEM_ZEROINIT.
例如:使用GPTR=0x0040来分配固定内存,并将它初始化为0。
GlobalAlloc的第二个参数是要分配的字节数。如果分配成功,GlobalAlloc返回IntPtr.Zero(大致等于非托管代码的null)。
由于某些原因,分配可能会出现失败;GlobalAlloc函数是从堆上分配指定的字节数。
|
|||
|