VirtualAlloc和HeapAlloc有什么区别?

时间:2021-03-23 03:20:51

There are lots of method to allocate memory in Windows environment, such as VirtualAlloc, HeapAlloc, malloc, new.

在Windows环境中,有很多方法可以分配内存,比如VirtualAlloc、HeapAlloc、malloc、new。

Thus, what's the difference among them?

那么,它们之间有什么区别呢?

6 个解决方案

#1


72  

Each API is for different uses. Each one also requires that you use the correct deallocation/freeing function when you're done with the memory.

每个API都有不同的用途。每一个都要求您在完成内存时使用正确的deallocation/释放函数。

VirtualAlloc

A low-level, Windows API that provides lots of options, but is mainly useful for people in fairly specific situations. Can only allocate memory in (edit: not 4KB) larger chunks. There are situations where you need it, but you'll know when you're in one of these situations. One of the most common is if you have to share memory directly with another process. Don't use it for general-purpose memory allocation. Use VirtualFree to deallocate.

一个低级的Windows API,它提供了很多选项,但主要用于特定情况下的人。只能在(编辑:不是4KB)较大的块中分配内存。有些情况下你需要它,但是当你处于这种情况时你就会知道。最常见的一种情况是,如果您必须直接与另一个进程共享内存。不要将其用于一般用途的内存分配。使用VirtualFree释放。

HeapAlloc

Allocates whatever size of memory you ask for, not in big chunks than VirtualAlloc. HeapAlloc knows when it needs to call VirtualAlloc and does so for you automatically. Like malloc, but is Windows-only, and provides a couple more options. Suitable for allocating general chunks of memory. Some Windows APIs may require that you use this to allocate memory that you pass to them, or use its companion HeapFree to free memory that they return to you.

分配你想要的内存大小,不是大的块,而是VirtualAlloc。HeapAlloc知道何时需要调用VirtualAlloc,并自动为您执行。像malloc一样,只是窗口,并提供了更多的选项。适合分配一般的内存块。一些Windows api可能要求您使用它来分配您传递给它们的内存,或者使用它的伙伴来释放它们返回给您的内存。

malloc

The C way of allocating memory. Prefer this if you are writing in C rather than C++, and you want your code to work on e.g. Unix computers too, or someone specifically says that you need to use it. Doesn't initialise the memory. Suitable for allocating general chunks of memory, like HeapAlloc. A simple API. Use free to deallocate. Visual C++'s malloc calls HeapAlloc.

分配内存的C方法。如果您是用C而不是c++编写代码,您希望您的代码可以在Unix计算机上工作,或者有人专门说您需要使用它。不初始化内存。适合分配一般的内存块,比如HeapAlloc。一个简单的API。使用*释放。Visual c++的malloc调用HeapAlloc。

new

The C++ way of allocating memory. Prefer this if you are writing in C++. It puts an object or objects into the allocated memory, too. Use delete to deallocate (or delete[] for arrays). Visual studio's new calls HeapAlloc, and then maybe initialises the objects, depending on how you call it.

分配内存的c++方法。如果你是用c++写的,你更喜欢这个。它也将对象或对象放入已分配的内存中。使用delete来释放(或删除[]数组)。Visual studio的新调用HeapAlloc,然后可能初始化对象,这取决于您如何调用它。

In recent C++ standards (C++11 and above), if you have to manually use delete, you're doing it wrong and should use a smart pointer like unique_ptr instead. From C++14 onwards, the same can be said of new (replaced with functions such as make_unique()).

在最近的c++标准(c++ 11和以上)中,如果您必须手动使用delete,那么您就做错了,应该使用像unique_ptr这样的智能指针。从c++ 14开始,同样可以使用new(替换为make_unique()等函数)。


There are also a couple of other similar functions like SysAllocString that you may be told you have to use in specific circumstances.

还有其他一些类似的函数,比如SysAllocString,你可能会被告知在特定情况下必须使用。

#2


24  

VirtualAlloc is a specialized allocation of the OS virtual memory (VM) system. Allocations in the VM system must be made at an allocation granularity which (the allocation granularity) is architecture dependent. Allocation in the VM system is one of the most basic forms of memory allocation. VM allocations can take several forms, memory is not necessarily dedicated or physically backed in RAM (though it can be). VM allocation is typically a special purpose type of allocation, either because of the allocation has to

VirtualAlloc是OS虚拟内存(VM)系统的一个专门配置。VM系统中的分配必须在分配粒度上进行(分配粒度)是依赖于体系结构的。在VM系统中分配是最基本的内存分配形式之一。VM分配可以采用多种形式,内存不一定是专用的或物理上支持RAM(尽管它可以是)。VM分配通常是一种特殊用途的分配,因为分配必须。

  • be very large,
  • 是非常大的,
  • needs to be shared,
  • 需要共享的,
  • must be aligned on a particular value (performance reasons) or
  • 必须对某个特定值(性能原因)进行对齐,还是?
  • the caller need not use all of this memory at once...
  • 调用者不必同时使用所有这些内存……
  • etc...
  • 等等……

HeapAlloc is essentially what malloc and new both eventually call. It is designed to be very fast and usable under many different types of scenarios of a general purpose allocation. It is the "Heap" in a classic sense. Heaps are actually setup by a VirtualAlloc, which is what is used to initially reserve allocation space from the OS. After the space is initialized by VirtualAlloc, various tables, lists and other data structures are configured to maintain and control the operation of the HEAP. Some of that operation is in the form of dynamically sizing (growing and shrinking) the heap, adapting the heap to particular usages (frequent allocations of some size), etc..

HeapAlloc实际上是malloc和new两者最终调用的。它设计得非常快,在一般用途分配的许多不同类型的场景下都可以使用。它是经典意义上的“堆”。堆实际上是由VirtualAlloc设置的,它是用来从操作系统中初始预留分配空间的。在VirtualAlloc初始化空间之后,将配置各种表、列表和其他数据结构,以维护和控制堆的操作。其中一些操作以动态调整大小(增长和收缩)的形式,将堆调整为特定的用途(一些大小的频繁分配),等等。

new and malloc are somewhat the same, malloc is essentially an exact call into HeapAlloc( heap-id-default ); new however, can [additionally] configure the allocated memory for C++ objects. For a given object, C++ will store vtables on the heap for each caller. These vtables are redirects for execution and form part of what gives C++ it's OO characteristics like inheritance, function overloading, etc...

新的和malloc在某种程度上是相同的,malloc本质上是对HeapAlloc(heapid -default)的精确调用;但是,可以[另外]为c++对象配置分配的内存。对于给定的对象,c++将为每个调用者在堆上存储vtables。这些vtables重定向用于执行,并构成了c++的一些特性,比如继承、函数重载等。

Some other common allocation methods like _alloca() and _malloca() are stack based; FileMappings are really allocated with VirtualAlloc and set with particular bit flags which designate those mappings to be of type FILE.

其他一些常见的分配方法,如_alloca()和_malloca()是基于堆栈的;filem实际上是用VirtualAlloc分配的,并设置了特定的位标志,将这些映射指定为类型文件。

Most of the time, you should allocate memory in a way which is consistent with the use of that memory ;). new in C++, malloc for C, VirtualAlloc for massive or IPC cases.

大多数时候,您应该以一种与内存使用一致的方式分配内存;新的c++, malloc为C, VirtualAlloc为大规模或IPC案例。

*** Note, large memory allocations done by HeapAlloc are actually shipped off to VirtualAlloc after some size (couple hundred k or 16 MB or something I forget, but fairly big :) ).

***注意,HeapAlloc所做的大量内存分配实际上是在一些大小之后被发送到VirtualAlloc(几百k或16mb或者其他我忘记的东西,但是相当大:))。

*** EDIT I briefly remarked about IPC and VirtualAlloc, there is also something very neat about a related VirtualAlloc which none of the responders to this question have discussed.

***编辑我简要地谈到了IPC和VirtualAlloc,关于一个相关的VirtualAlloc也有一些非常简洁的东西,没有一个响应者讨论过这个问题。

VirtualAllocEx is what one process can use to allocate memory in an address space of a different process. Most typically, this is used in combination to get remote execution in the context of another process via CreateRemoteThread (similar to CreateThread, the thread is just run in the other process).

VirtualAllocEx是一个进程可以用来在不同进程的地址空间中分配内存的过程。最典型的情况是,通过CreateRemoteThread(类似于CreateThread,线程在另一个进程中运行),在组合中使用这个方法来获得远程执行。

#3


10  

It is very important to understand the distinction between memory allocation APIs (in Windows) if you plan on using a language that requires memory management (like C or C++.) And the best way to illustrate it IMHO is with a diagram:

如果您打算使用需要内存管理的语言(如C或c++),那么理解内存分配api(在Windows中)的区别是非常重要的。用图表来说明IMHO的最佳方法是:

VirtualAlloc和HeapAlloc有什么区别?

Note that this is a very simplified, Windows-specific view.

请注意,这是一个非常简化的窗口特定视图。

The way to understand this diagram is that the higher on the diagram a memory allocation method is, the higher level implementation it uses. But let's start from the bottom.

理解这张图的方法是,图上的内存分配方法越高,它使用的级别越高。让我们从底部开始。

Kernel-Mode Memory Manager

It provides all memory reservations & allocations for the operating system, as well as support for memory-mapped files, shared memory, copy-on-write operations, etc. It's not directly accessible from the user-mode code, so I'll skip it here.

它提供了操作系统的所有内存预订和分配,以及对内存映射文件、共享内存、复制-写操作等的支持。它不能直接从用户模式代码访问,所以我将跳过它。

VirtualAlloc / VirtualFree

These are the lowest level APIs available from the user mode. The VirtualAlloc function basically invokes ZwAllocateVirtualMemory that in turn does a quick syscall to ring0 to relegate further processing to the kernel memory manager. It is also the fastest method to reserve/allocate block of new memory from all available in the user mode.

这些是用户模式中可用的最低级别api。VirtualAlloc函数主要调用ZwAllocateVirtualMemory,它反过来对ring0进行快速的syscall,将进一步的处理降级到内核内存管理器。它也是在用户模式中保留/分配新内存块的最快方法。

But it comes with two main conditions:

但它有两个主要条件:

  • It only allocates memory blocks aligned on the system granularity boundary.

    它只分配在系统粒度边界上对齐的内存块。

  • It only allocates memory blocks of the size that is the multiple of the system granularity.

    它只分配系统粒度的倍数的内存块。

So what is this system granularity? You can get it by calling GetSystemInfo. It is returned as the dwAllocationGranularity parameter. Its value is implementation (and possibly hardware) specific, but on many 64-bit Windows systems it is set at 0x10000 bytes, or 64K.

那么这个系统的粒度是什么呢?你可以通过调用GetSystemInfo来获得它。它作为dwallocation粒度参数返回。它的值是实现(可能是硬件),但是在许多64位Windows系统上,它设置为0x10000字节,或者64K。

So what all this means, is that if you try to allocate, say just an 8 byte memory block with VirtualAlloc:

所以这意味着,如果你试图分配,比如说一个8字节的内存块和VirtualAlloc:

void* pAddress = VirtualAlloc(NULL, 8, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

If successful, pAddress will be aligned on the 0x10000 byte boundary. And even though you requested only 8 bytes, the actual memory block that you will get will be the entire page (or, something like 4K bytes. The exact page size is returned in the dwPageSize parameter.) But, on top of that, the entire memory block spanning 0x10000 bytes (or 64K in most cases) from pAddress will not be available for any further allocations. So in a sense, by allocating 8 bytes you could as well be asking for 65536.

如果成功,pAddress将在0x10000字节边界上对齐。即使您只请求了8个字节,您将得到的实际内存块将是整个页面(或者类似4K字节的内容)。在dwPageSize参数中返回精确的页面大小。但是,最重要的是,从pAddress中跨越0x10000字节(或64K)的整个内存块将不能用于任何进一步的分配。所以在某种意义上,通过分配8个字节,你也可以要求65536。

So the moral of the story here is not to substitute VirtualAlloc for generic memory allocations in your application. It must be used for very specific cases, as is done with the heap below. (Usually for reserving/allocating large blocks of memory.)

因此,这里的故事的寓意是,不要用VirtualAlloc来替代应用程序中的通用内存分配。它必须用于非常特殊的情况,如下面的堆所做的那样。(通常用于保留/分配大块内存。)

Using VirtualAlloc incorrectly can lead to severe memory fragmentation.

错误地使用VirtualAlloc会导致严重的内存碎片。

HeapCreate / HeapAlloc / HeapFree / HeapDestroy

In a nutshell, the heap functions are basically a wrapper for VirtualAlloc function. Other answers here provide a pretty good concept of it. I'll add that, in a very simplistic view, the way heap works is this:

简单地说,堆函数基本上是VirtualAlloc函数的包装器。这里的其他答案提供了一个很好的概念。我要补充一点,在一个非常简单的视图中,堆的工作方式是这样的:

  • HeapCreate reserves a large block of virtual memory by calling VirtualAlloc internally (or ZwAllocateVirtualMemory to be specific). It also sets up an internal data structure that can track further smaller size allocations within the reserved block of virtual memory.

    HeapCreate通过在内部调用VirtualAlloc(或ZwAllocateVirtualMemory)来保留大量的虚拟内存。它还设置了一个内部数据结构,可以在虚拟内存的保留块中跟踪更小的大小分配。

  • Any calls to HeapAlloc and HeapFree do not actually allocate/free any new memory (unless, of course the request exceeds what has been already reserved in HeapCreate) but instead they meter out (or commit) a previously reserved large chunk, by dissecting it into smaller memory blocks that a user requests.

    任何对HeapAlloc和HeapFree的调用都不会真正地分配/释放任何新的内存(除非,当然请求超过了在HeapCreate中已经保留的),而是通过将其分割为一个用户请求的较小内存块,从而将(或提交)一个先前保留的大块。

  • HeapDestroy in turn calls VirtualFree that actually frees the virtual memory.

    HeapDestroy反过来调用VirtualFree,它实际上释放了虚拟内存。

So all this makes heap functions perfect candidates for generic memory allocations in your application. It is great for arbitrary size memory allocations. But a small price to pay for the convenience of the heap functions is that they introduce a slight overhead over VirtualAlloc when reserving larger blocks of memory.

因此,所有这些使堆函数成为应用程序中通用内存分配的完美候选。它对于任意大小的内存分配非常有用。但是为了方便堆函数而付出的一个小代价是,当保留较大的内存块时,它们会在VirtualAlloc上引入一个略微的开销。

Another good thing about heap is that you don't really need to create one. It is generally created for you when your process starts. So one can access it by calling GetProcessHeap function.

堆的另一个好处是您不需要创建一个。它通常是在您的流程启动时为您创建的。我们可以通过调用GetProcessHeap函数来访问它。

malloc / free

Is a language-specific wrapper for the heap functions. Unlike HeapAlloc, HeapFree, etc. these functions will work not only if your code is compiled for Windows, but also for other operating systems (such as Linux, etc.)

是堆函数的特定于语言的包装器。与HeapAlloc、HeapFree等不同,这些函数不仅适用于为Windows编译的代码,也适用于其他操作系统(如Linux等)。

This is a recommended way to allocate/free memory if you program in C. (Unless, you're coding a specific kernel mode device driver.)

这是一种推荐的方法来分配/释放内存,如果您在c中编程(除非,您正在编写一个特定的内核模式设备驱动程序)。

new / delete

Come as a high level (well, for C++) memory management operators. They are specific for the C++ language, and like malloc for C, are also the wrappers for the heap functions. They also have a whole bunch of their own code that deals C++-specific initialization of constructors, deallocation in destructors, etc.

作为一个高层次的(对c++)内存管理操作符来说。它们是特定于c++语言的,并且与malloc (C)一样,也是堆函数的包装器。他们还有一大堆自己的代码,可以处理c++特定的构造函数初始化、析构函数的deallocation等。

These functions are a recommended way to allocate/free memory and objects if you program in C++.

如果你用c++编程,这些函数是分配/释放内存和对象的推荐方法。


Lastly, one comment I want to make about what has been said in other responses about using VirtualAlloc to share memory between processes. VirtualAlloc by itself does not allow sharing of its reserved/allocated memory with other processes. For that one needs to use CreateFileMapping API that can create a named virtual memory block that can be shared with other processes. It can also map a file on disk into virtual memory for read/write access. But that is another topic.

最后,我想谈谈关于使用VirtualAlloc在进程间共享内存的其他响应中所提到的内容。VirtualAlloc本身不允许与其他进程共享其保留/分配的内存。为此,需要使用CreateFileMapping API来创建可与其他进程共享的命名虚拟内存块。它还可以将磁盘上的文件映射到虚拟内存中,用于读/写访问。但这是另一个话题。

#4


6  

In outline:

在概述:

  • VirtualAlloc, HeapAlloc etc. are Windows APIs that allocate memory of various types from the OS directly. VirtualAlloc manages pages in the Windows virtual memory system, while HeapAlloc allocates from a specific OS heap. Frankly, you are unlikely to ever need to use eiither of them.

    VirtualAlloc, HeapAlloc等是Windows api,它可以直接从操作系统分配各种类型的内存。VirtualAlloc在Windows虚拟内存系统中管理页面,而HeapAlloc从一个特定的OS堆中分配。坦率地说,你不太可能需要使用它们。

  • malloc is a Standard C (and C++) library function that allocates memory to your process. Implementations of malloc will typically use one of the OS APIs to create a pool of memory when your app starts and then allocate from it as you make malloc requests

    malloc是一个标准的C(和c++)库函数,它将内存分配给您的进程。malloc的实现通常会使用一个OS api来创建一个内存池,当你的应用程序启动时,当你做malloc请求时,它会从中分配内存。

  • new is a Standard C++ operator which allocates memory and then calls constructors appropriately on that memory. It may be implemented in terms of malloc or in terms of the OS APIs, in which case it too will typically create a memory pool on application startup.

    new是一个标准的c++操作符,它分配内存,然后在内存中适当地调用构造函数。它可以用malloc或OS api来实现,在这种情况下,它也会在应用程序启动时创建一个内存池。

#5


3  

VirtualAlloc ===> sbrk() under UNIX

在UNIX下的VirtualAlloc ===> sbrk()。

HeapAlloc ====> malloc() under UNIX

在UNIX下,HeapAlloc ====> malloc()。

#6


2  

VirtualAlloc => Allocates straight into virtual memory, you reserve/commit in blocks. This is great for large allocations, for example large arrays.

VirtualAlloc =>直接分配到虚拟内存中,在块中保留/提交。这对于大型的分配非常有用,例如大型数组。

HeapAlloc / new => allocates the memory on the default heap (or any other heap that you may create). This allocates per object and is great for smaller objects. The default heap is serializable therefore it has guarantee thread allocation (this can cause some issues on high performance scenarios and that's why you can create your own heaps).

HeapAlloc / new =>在默认堆(或您可能创建的任何其他堆)上分配内存。它分配每个对象,对于较小的对象非常有用。默认的堆是可序列化的,因此它可以保证线程分配(这可能会导致一些关于高性能场景的问题,这就是为什么您可以创建自己的堆)。

malloc => uses the C runtime heap, similar to HeapAlloc but it is common for compatibility scenarios.

malloc =>使用C运行时堆,类似于HeapAlloc,但在兼容性场景中很常见。

In a nutshell, the heap is just a chunk of virtual memory that is governed by a heap manager (rather than raw virtual memory)

简单地说,堆只是由堆管理器管理的虚拟内存块(而不是原始的虚拟内存)

The last model on the memory world is memory mapped files, this scenario is great for large chunk of data (like large files). This is used internally when you open an EXE (it does not load the EXE in memory, just creates a memory mapped file).

内存世界上的最后一个模型是内存映射文件,这个场景对于大量数据(比如大文件)来说非常好。当您打开EXE(它不会在内存中加载EXE,只创建一个内存映射文件)时,就会在内部使用它。

#1


72  

Each API is for different uses. Each one also requires that you use the correct deallocation/freeing function when you're done with the memory.

每个API都有不同的用途。每一个都要求您在完成内存时使用正确的deallocation/释放函数。

VirtualAlloc

A low-level, Windows API that provides lots of options, but is mainly useful for people in fairly specific situations. Can only allocate memory in (edit: not 4KB) larger chunks. There are situations where you need it, but you'll know when you're in one of these situations. One of the most common is if you have to share memory directly with another process. Don't use it for general-purpose memory allocation. Use VirtualFree to deallocate.

一个低级的Windows API,它提供了很多选项,但主要用于特定情况下的人。只能在(编辑:不是4KB)较大的块中分配内存。有些情况下你需要它,但是当你处于这种情况时你就会知道。最常见的一种情况是,如果您必须直接与另一个进程共享内存。不要将其用于一般用途的内存分配。使用VirtualFree释放。

HeapAlloc

Allocates whatever size of memory you ask for, not in big chunks than VirtualAlloc. HeapAlloc knows when it needs to call VirtualAlloc and does so for you automatically. Like malloc, but is Windows-only, and provides a couple more options. Suitable for allocating general chunks of memory. Some Windows APIs may require that you use this to allocate memory that you pass to them, or use its companion HeapFree to free memory that they return to you.

分配你想要的内存大小,不是大的块,而是VirtualAlloc。HeapAlloc知道何时需要调用VirtualAlloc,并自动为您执行。像malloc一样,只是窗口,并提供了更多的选项。适合分配一般的内存块。一些Windows api可能要求您使用它来分配您传递给它们的内存,或者使用它的伙伴来释放它们返回给您的内存。

malloc

The C way of allocating memory. Prefer this if you are writing in C rather than C++, and you want your code to work on e.g. Unix computers too, or someone specifically says that you need to use it. Doesn't initialise the memory. Suitable for allocating general chunks of memory, like HeapAlloc. A simple API. Use free to deallocate. Visual C++'s malloc calls HeapAlloc.

分配内存的C方法。如果您是用C而不是c++编写代码,您希望您的代码可以在Unix计算机上工作,或者有人专门说您需要使用它。不初始化内存。适合分配一般的内存块,比如HeapAlloc。一个简单的API。使用*释放。Visual c++的malloc调用HeapAlloc。

new

The C++ way of allocating memory. Prefer this if you are writing in C++. It puts an object or objects into the allocated memory, too. Use delete to deallocate (or delete[] for arrays). Visual studio's new calls HeapAlloc, and then maybe initialises the objects, depending on how you call it.

分配内存的c++方法。如果你是用c++写的,你更喜欢这个。它也将对象或对象放入已分配的内存中。使用delete来释放(或删除[]数组)。Visual studio的新调用HeapAlloc,然后可能初始化对象,这取决于您如何调用它。

In recent C++ standards (C++11 and above), if you have to manually use delete, you're doing it wrong and should use a smart pointer like unique_ptr instead. From C++14 onwards, the same can be said of new (replaced with functions such as make_unique()).

在最近的c++标准(c++ 11和以上)中,如果您必须手动使用delete,那么您就做错了,应该使用像unique_ptr这样的智能指针。从c++ 14开始,同样可以使用new(替换为make_unique()等函数)。


There are also a couple of other similar functions like SysAllocString that you may be told you have to use in specific circumstances.

还有其他一些类似的函数,比如SysAllocString,你可能会被告知在特定情况下必须使用。

#2


24  

VirtualAlloc is a specialized allocation of the OS virtual memory (VM) system. Allocations in the VM system must be made at an allocation granularity which (the allocation granularity) is architecture dependent. Allocation in the VM system is one of the most basic forms of memory allocation. VM allocations can take several forms, memory is not necessarily dedicated or physically backed in RAM (though it can be). VM allocation is typically a special purpose type of allocation, either because of the allocation has to

VirtualAlloc是OS虚拟内存(VM)系统的一个专门配置。VM系统中的分配必须在分配粒度上进行(分配粒度)是依赖于体系结构的。在VM系统中分配是最基本的内存分配形式之一。VM分配可以采用多种形式,内存不一定是专用的或物理上支持RAM(尽管它可以是)。VM分配通常是一种特殊用途的分配,因为分配必须。

  • be very large,
  • 是非常大的,
  • needs to be shared,
  • 需要共享的,
  • must be aligned on a particular value (performance reasons) or
  • 必须对某个特定值(性能原因)进行对齐,还是?
  • the caller need not use all of this memory at once...
  • 调用者不必同时使用所有这些内存……
  • etc...
  • 等等……

HeapAlloc is essentially what malloc and new both eventually call. It is designed to be very fast and usable under many different types of scenarios of a general purpose allocation. It is the "Heap" in a classic sense. Heaps are actually setup by a VirtualAlloc, which is what is used to initially reserve allocation space from the OS. After the space is initialized by VirtualAlloc, various tables, lists and other data structures are configured to maintain and control the operation of the HEAP. Some of that operation is in the form of dynamically sizing (growing and shrinking) the heap, adapting the heap to particular usages (frequent allocations of some size), etc..

HeapAlloc实际上是malloc和new两者最终调用的。它设计得非常快,在一般用途分配的许多不同类型的场景下都可以使用。它是经典意义上的“堆”。堆实际上是由VirtualAlloc设置的,它是用来从操作系统中初始预留分配空间的。在VirtualAlloc初始化空间之后,将配置各种表、列表和其他数据结构,以维护和控制堆的操作。其中一些操作以动态调整大小(增长和收缩)的形式,将堆调整为特定的用途(一些大小的频繁分配),等等。

new and malloc are somewhat the same, malloc is essentially an exact call into HeapAlloc( heap-id-default ); new however, can [additionally] configure the allocated memory for C++ objects. For a given object, C++ will store vtables on the heap for each caller. These vtables are redirects for execution and form part of what gives C++ it's OO characteristics like inheritance, function overloading, etc...

新的和malloc在某种程度上是相同的,malloc本质上是对HeapAlloc(heapid -default)的精确调用;但是,可以[另外]为c++对象配置分配的内存。对于给定的对象,c++将为每个调用者在堆上存储vtables。这些vtables重定向用于执行,并构成了c++的一些特性,比如继承、函数重载等。

Some other common allocation methods like _alloca() and _malloca() are stack based; FileMappings are really allocated with VirtualAlloc and set with particular bit flags which designate those mappings to be of type FILE.

其他一些常见的分配方法,如_alloca()和_malloca()是基于堆栈的;filem实际上是用VirtualAlloc分配的,并设置了特定的位标志,将这些映射指定为类型文件。

Most of the time, you should allocate memory in a way which is consistent with the use of that memory ;). new in C++, malloc for C, VirtualAlloc for massive or IPC cases.

大多数时候,您应该以一种与内存使用一致的方式分配内存;新的c++, malloc为C, VirtualAlloc为大规模或IPC案例。

*** Note, large memory allocations done by HeapAlloc are actually shipped off to VirtualAlloc after some size (couple hundred k or 16 MB or something I forget, but fairly big :) ).

***注意,HeapAlloc所做的大量内存分配实际上是在一些大小之后被发送到VirtualAlloc(几百k或16mb或者其他我忘记的东西,但是相当大:))。

*** EDIT I briefly remarked about IPC and VirtualAlloc, there is also something very neat about a related VirtualAlloc which none of the responders to this question have discussed.

***编辑我简要地谈到了IPC和VirtualAlloc,关于一个相关的VirtualAlloc也有一些非常简洁的东西,没有一个响应者讨论过这个问题。

VirtualAllocEx is what one process can use to allocate memory in an address space of a different process. Most typically, this is used in combination to get remote execution in the context of another process via CreateRemoteThread (similar to CreateThread, the thread is just run in the other process).

VirtualAllocEx是一个进程可以用来在不同进程的地址空间中分配内存的过程。最典型的情况是,通过CreateRemoteThread(类似于CreateThread,线程在另一个进程中运行),在组合中使用这个方法来获得远程执行。

#3


10  

It is very important to understand the distinction between memory allocation APIs (in Windows) if you plan on using a language that requires memory management (like C or C++.) And the best way to illustrate it IMHO is with a diagram:

如果您打算使用需要内存管理的语言(如C或c++),那么理解内存分配api(在Windows中)的区别是非常重要的。用图表来说明IMHO的最佳方法是:

VirtualAlloc和HeapAlloc有什么区别?

Note that this is a very simplified, Windows-specific view.

请注意,这是一个非常简化的窗口特定视图。

The way to understand this diagram is that the higher on the diagram a memory allocation method is, the higher level implementation it uses. But let's start from the bottom.

理解这张图的方法是,图上的内存分配方法越高,它使用的级别越高。让我们从底部开始。

Kernel-Mode Memory Manager

It provides all memory reservations & allocations for the operating system, as well as support for memory-mapped files, shared memory, copy-on-write operations, etc. It's not directly accessible from the user-mode code, so I'll skip it here.

它提供了操作系统的所有内存预订和分配,以及对内存映射文件、共享内存、复制-写操作等的支持。它不能直接从用户模式代码访问,所以我将跳过它。

VirtualAlloc / VirtualFree

These are the lowest level APIs available from the user mode. The VirtualAlloc function basically invokes ZwAllocateVirtualMemory that in turn does a quick syscall to ring0 to relegate further processing to the kernel memory manager. It is also the fastest method to reserve/allocate block of new memory from all available in the user mode.

这些是用户模式中可用的最低级别api。VirtualAlloc函数主要调用ZwAllocateVirtualMemory,它反过来对ring0进行快速的syscall,将进一步的处理降级到内核内存管理器。它也是在用户模式中保留/分配新内存块的最快方法。

But it comes with two main conditions:

但它有两个主要条件:

  • It only allocates memory blocks aligned on the system granularity boundary.

    它只分配在系统粒度边界上对齐的内存块。

  • It only allocates memory blocks of the size that is the multiple of the system granularity.

    它只分配系统粒度的倍数的内存块。

So what is this system granularity? You can get it by calling GetSystemInfo. It is returned as the dwAllocationGranularity parameter. Its value is implementation (and possibly hardware) specific, but on many 64-bit Windows systems it is set at 0x10000 bytes, or 64K.

那么这个系统的粒度是什么呢?你可以通过调用GetSystemInfo来获得它。它作为dwallocation粒度参数返回。它的值是实现(可能是硬件),但是在许多64位Windows系统上,它设置为0x10000字节,或者64K。

So what all this means, is that if you try to allocate, say just an 8 byte memory block with VirtualAlloc:

所以这意味着,如果你试图分配,比如说一个8字节的内存块和VirtualAlloc:

void* pAddress = VirtualAlloc(NULL, 8, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

If successful, pAddress will be aligned on the 0x10000 byte boundary. And even though you requested only 8 bytes, the actual memory block that you will get will be the entire page (or, something like 4K bytes. The exact page size is returned in the dwPageSize parameter.) But, on top of that, the entire memory block spanning 0x10000 bytes (or 64K in most cases) from pAddress will not be available for any further allocations. So in a sense, by allocating 8 bytes you could as well be asking for 65536.

如果成功,pAddress将在0x10000字节边界上对齐。即使您只请求了8个字节,您将得到的实际内存块将是整个页面(或者类似4K字节的内容)。在dwPageSize参数中返回精确的页面大小。但是,最重要的是,从pAddress中跨越0x10000字节(或64K)的整个内存块将不能用于任何进一步的分配。所以在某种意义上,通过分配8个字节,你也可以要求65536。

So the moral of the story here is not to substitute VirtualAlloc for generic memory allocations in your application. It must be used for very specific cases, as is done with the heap below. (Usually for reserving/allocating large blocks of memory.)

因此,这里的故事的寓意是,不要用VirtualAlloc来替代应用程序中的通用内存分配。它必须用于非常特殊的情况,如下面的堆所做的那样。(通常用于保留/分配大块内存。)

Using VirtualAlloc incorrectly can lead to severe memory fragmentation.

错误地使用VirtualAlloc会导致严重的内存碎片。

HeapCreate / HeapAlloc / HeapFree / HeapDestroy

In a nutshell, the heap functions are basically a wrapper for VirtualAlloc function. Other answers here provide a pretty good concept of it. I'll add that, in a very simplistic view, the way heap works is this:

简单地说,堆函数基本上是VirtualAlloc函数的包装器。这里的其他答案提供了一个很好的概念。我要补充一点,在一个非常简单的视图中,堆的工作方式是这样的:

  • HeapCreate reserves a large block of virtual memory by calling VirtualAlloc internally (or ZwAllocateVirtualMemory to be specific). It also sets up an internal data structure that can track further smaller size allocations within the reserved block of virtual memory.

    HeapCreate通过在内部调用VirtualAlloc(或ZwAllocateVirtualMemory)来保留大量的虚拟内存。它还设置了一个内部数据结构,可以在虚拟内存的保留块中跟踪更小的大小分配。

  • Any calls to HeapAlloc and HeapFree do not actually allocate/free any new memory (unless, of course the request exceeds what has been already reserved in HeapCreate) but instead they meter out (or commit) a previously reserved large chunk, by dissecting it into smaller memory blocks that a user requests.

    任何对HeapAlloc和HeapFree的调用都不会真正地分配/释放任何新的内存(除非,当然请求超过了在HeapCreate中已经保留的),而是通过将其分割为一个用户请求的较小内存块,从而将(或提交)一个先前保留的大块。

  • HeapDestroy in turn calls VirtualFree that actually frees the virtual memory.

    HeapDestroy反过来调用VirtualFree,它实际上释放了虚拟内存。

So all this makes heap functions perfect candidates for generic memory allocations in your application. It is great for arbitrary size memory allocations. But a small price to pay for the convenience of the heap functions is that they introduce a slight overhead over VirtualAlloc when reserving larger blocks of memory.

因此,所有这些使堆函数成为应用程序中通用内存分配的完美候选。它对于任意大小的内存分配非常有用。但是为了方便堆函数而付出的一个小代价是,当保留较大的内存块时,它们会在VirtualAlloc上引入一个略微的开销。

Another good thing about heap is that you don't really need to create one. It is generally created for you when your process starts. So one can access it by calling GetProcessHeap function.

堆的另一个好处是您不需要创建一个。它通常是在您的流程启动时为您创建的。我们可以通过调用GetProcessHeap函数来访问它。

malloc / free

Is a language-specific wrapper for the heap functions. Unlike HeapAlloc, HeapFree, etc. these functions will work not only if your code is compiled for Windows, but also for other operating systems (such as Linux, etc.)

是堆函数的特定于语言的包装器。与HeapAlloc、HeapFree等不同,这些函数不仅适用于为Windows编译的代码,也适用于其他操作系统(如Linux等)。

This is a recommended way to allocate/free memory if you program in C. (Unless, you're coding a specific kernel mode device driver.)

这是一种推荐的方法来分配/释放内存,如果您在c中编程(除非,您正在编写一个特定的内核模式设备驱动程序)。

new / delete

Come as a high level (well, for C++) memory management operators. They are specific for the C++ language, and like malloc for C, are also the wrappers for the heap functions. They also have a whole bunch of their own code that deals C++-specific initialization of constructors, deallocation in destructors, etc.

作为一个高层次的(对c++)内存管理操作符来说。它们是特定于c++语言的,并且与malloc (C)一样,也是堆函数的包装器。他们还有一大堆自己的代码,可以处理c++特定的构造函数初始化、析构函数的deallocation等。

These functions are a recommended way to allocate/free memory and objects if you program in C++.

如果你用c++编程,这些函数是分配/释放内存和对象的推荐方法。


Lastly, one comment I want to make about what has been said in other responses about using VirtualAlloc to share memory between processes. VirtualAlloc by itself does not allow sharing of its reserved/allocated memory with other processes. For that one needs to use CreateFileMapping API that can create a named virtual memory block that can be shared with other processes. It can also map a file on disk into virtual memory for read/write access. But that is another topic.

最后,我想谈谈关于使用VirtualAlloc在进程间共享内存的其他响应中所提到的内容。VirtualAlloc本身不允许与其他进程共享其保留/分配的内存。为此,需要使用CreateFileMapping API来创建可与其他进程共享的命名虚拟内存块。它还可以将磁盘上的文件映射到虚拟内存中,用于读/写访问。但这是另一个话题。

#4


6  

In outline:

在概述:

  • VirtualAlloc, HeapAlloc etc. are Windows APIs that allocate memory of various types from the OS directly. VirtualAlloc manages pages in the Windows virtual memory system, while HeapAlloc allocates from a specific OS heap. Frankly, you are unlikely to ever need to use eiither of them.

    VirtualAlloc, HeapAlloc等是Windows api,它可以直接从操作系统分配各种类型的内存。VirtualAlloc在Windows虚拟内存系统中管理页面,而HeapAlloc从一个特定的OS堆中分配。坦率地说,你不太可能需要使用它们。

  • malloc is a Standard C (and C++) library function that allocates memory to your process. Implementations of malloc will typically use one of the OS APIs to create a pool of memory when your app starts and then allocate from it as you make malloc requests

    malloc是一个标准的C(和c++)库函数,它将内存分配给您的进程。malloc的实现通常会使用一个OS api来创建一个内存池,当你的应用程序启动时,当你做malloc请求时,它会从中分配内存。

  • new is a Standard C++ operator which allocates memory and then calls constructors appropriately on that memory. It may be implemented in terms of malloc or in terms of the OS APIs, in which case it too will typically create a memory pool on application startup.

    new是一个标准的c++操作符,它分配内存,然后在内存中适当地调用构造函数。它可以用malloc或OS api来实现,在这种情况下,它也会在应用程序启动时创建一个内存池。

#5


3  

VirtualAlloc ===> sbrk() under UNIX

在UNIX下的VirtualAlloc ===> sbrk()。

HeapAlloc ====> malloc() under UNIX

在UNIX下,HeapAlloc ====> malloc()。

#6


2  

VirtualAlloc => Allocates straight into virtual memory, you reserve/commit in blocks. This is great for large allocations, for example large arrays.

VirtualAlloc =>直接分配到虚拟内存中,在块中保留/提交。这对于大型的分配非常有用,例如大型数组。

HeapAlloc / new => allocates the memory on the default heap (or any other heap that you may create). This allocates per object and is great for smaller objects. The default heap is serializable therefore it has guarantee thread allocation (this can cause some issues on high performance scenarios and that's why you can create your own heaps).

HeapAlloc / new =>在默认堆(或您可能创建的任何其他堆)上分配内存。它分配每个对象,对于较小的对象非常有用。默认的堆是可序列化的,因此它可以保证线程分配(这可能会导致一些关于高性能场景的问题,这就是为什么您可以创建自己的堆)。

malloc => uses the C runtime heap, similar to HeapAlloc but it is common for compatibility scenarios.

malloc =>使用C运行时堆,类似于HeapAlloc,但在兼容性场景中很常见。

In a nutshell, the heap is just a chunk of virtual memory that is governed by a heap manager (rather than raw virtual memory)

简单地说,堆只是由堆管理器管理的虚拟内存块(而不是原始的虚拟内存)

The last model on the memory world is memory mapped files, this scenario is great for large chunk of data (like large files). This is used internally when you open an EXE (it does not load the EXE in memory, just creates a memory mapped file).

内存世界上的最后一个模型是内存映射文件,这个场景对于大量数据(比如大文件)来说非常好。当您打开EXE(它不会在内存中加载EXE,只创建一个内存映射文件)时,就会在内部使用它。