Nice programing

VirtualAlloc과 HeapAlloc의 차이점은 무엇입니까?

nicepro 2020. 10. 16. 08:03
반응형

VirtualAlloc과 HeapAlloc의 차이점은 무엇입니까?


같은 Windows 환경에서 메모리를 할당하는 방법은 많이있다 VirtualAlloc, HeapAlloc, malloc, new.

따라서 그들 사이의 차이점은 무엇입니까?


각 API는 서로 다른 용도로 사용됩니다. 또한 각각은 메모리를 다 사용할 때 올바른 할당 해제 / 해제 기능을 사용해야합니다.

VirtualAlloc

많은 옵션을 제공하지만 주로 상당히 특정한 상황에있는 사람들에게 유용한 저수준 Windows API입니다. 더 큰 청크에만 메모리를 할당 할 수 있습니다 (편집 : 4KB 아님). 필요한 상황이 있지만 이러한 상황 중 하나에 해당하는 경우 알 수 있습니다. 가장 일반적인 방법 중 하나는 다른 프로세스와 직접 메모리를 공유해야하는 경우입니다. 범용 메모리 할당에는 사용하지 마십시오. VirtualFree할당을 해제하는 데 사용 합니다.

HeapAlloc

원하는 크기의 메모리를 할당합니다 VirtualAlloc.. HeapAlloc전화 VirtualAlloc필요한시기를 알고 자동으로 수행합니다. 과 유사 malloc하지만 Windows 전용이며 몇 가지 추가 옵션을 제공합니다. 일반적인 메모리 청크 할당에 적합합니다. 일부 Windows API에서는이를 사용하여 전달한 메모리를 할당하거나 해당 API를 사용하여 HeapFree반환되는 메모리를 해제해야 할 수 있습니다.

Malloc

메모리를 할당하는 C 방식. C ++가 아닌 C로 작성하고, 예를 들어 Unix 컴퓨터에서도 코드가 작동하기를 원하거나 누군가가 그것을 사용해야한다고 특별히 말하는 경우 이것을 선호합니다. 메모리를 초기화하지 않습니다. 같은 일반적인 메모리 청크 할당에 적합합니다 HeapAlloc. 간단한 API. free할당을 해제하는 데 사용 합니다. Visual C ++의 malloc호출 HeapAlloc.

새로운

메모리를 할당하는 C ++ 방식. C ++로 작성하는 경우 선호합니다. 객체를 할당 된 메모리에도 넣습니다. 사용 delete할당을 해제 (또는 delete[]배열). Visual Studio에서를 new호출 HeapAlloc한 다음 호출 방법에 따라 개체를 초기화 할 수 있습니다.

수동으로 사용해야하는 경우 최근 C ++ 표준 (C ++ 11 이상)에서는 delete, 당신은 잘못하고 있어요하고 사용해야하는 스마트 포인터 처럼 unique_ptr대신. C ++ 14부터는 똑같이 말할 수 있습니다 new(와 같은 함수로 대체 됨 make_unique()).


SysAllocString특정 상황에서 사용해야하는 것과 같은 몇 가지 다른 유사한 기능도 있습니다.


VirtualAllocOS VM (가상 메모리) 시스템의 특수 할당입니다. VM 시스템의 할당은 아키텍처에 따라 달라지는 할당 단위 (할당 단위)로 이루어져야합니다. VM 시스템에서의 할당은 메모리 할당의 가장 기본적인 형태 중 하나입니다. VM 할당은 여러 가지 형태를 취할 수 있으며 메모리가 반드시 RAM에 전용되거나 물리적으로 백업되는 것은 아닙니다 (그럴 수도 있음). VM 할당은 일반적으로 할당해야하는 특수 목적 유형의 할당입니다.

  • 매우 크고
  • 공유해야합니다.
  • 특정 값 (성능 이유)에 따라 정렬되어야합니다.
  • 발신자는이 모든 메모리를 한 번에 사용할 필요가 없습니다.
  • 기타...

HeapAlloc무엇을 본질적으로 malloc하고 new모두가 결국 호출합니다. 범용 할당의 다양한 유형의 시나리오에서 매우 빠르고 사용 가능하도록 설계되었습니다. 고전적인 의미의 "힙"입니다. 힙은 실제로 OS에서 할당 공간 VirtualAlloc처음 예약 하는 데 사용되는에 의해 설정됩니다 . 에 의해 공간이 초기화 된 VirtualAlloc후 다양한 테이블, 목록 및 기타 데이터 구조가 구성되어 HEAP의 작동을 유지하고 제어합니다. 이 작업 중 일부는 힙을 동적으로 크기 조정 (증가 및 축소)하는 형태로, 힙을 특정 용도 (일부 크기의 빈번한 할당) 등에 맞게 조정합니다.

new그리고 malloc다소 동일하며 malloc본질적으로 정확한 호출입니다 HeapAlloc( heap-id-default ). new그러나 [추가적으로] C ++ 객체에 할당 된 메모리를 구성 할 수 있습니다 . 주어진 객체에 대해 C ++는 각 호출자의 힙에 vtables를 저장합니다. 이러한 vtable은 실행을위한 리디렉션이며 상속, 함수 오버로딩 등과 같은 OO 특성을 C ++에 제공하는 요소의 일부를 구성합니다.

_alloca()같은 다른 일반적인 할당 방법 _malloca()스택 기반입니다. FileMapping은 실제로 VirtualAlloc해당 매핑을 유형으로 지정하는 특정 비트 플래그로 할당 되고 설정됩니다 FILE.

대부분의 경우 해당 메모리 사용과 일치하는 방식으로 메모리를 할당해야합니다. newC ++, mallocC, VirtualAlloc대규모 또는 IPC의 경우.

*** 참고로,에서 수행 한 대용량 메모리 할당 HeapAlloc은 실제로 VirtualAlloc일정 크기 (몇 백 k 또는 16MB 또는 내가 잊은 것이지만 상당히 큽니다 :)) 이후로 배송됩니다 .

*** 편집 나는 IPC에 대해 간략히 언급했으며이 질문에 대한 응답자 중 누구도 논의하지 않은 VirtualAlloc관련 항목에 대해 매우 깔끔한 VirtualAlloc것도 있습니다.

VirtualAllocEx 는 한 프로세스가 다른 프로세스 의 주소 공간에 메모리를 할당하는 데 사용할 수있는 것입니다. 가장 일반적으로 이것은 CreateRemoteThread 를 통해 다른 프로세스의 컨텍스트에서 원격 실행을 얻기 위해 조합 하여 사용 됩니다 ( , 스레드는 다른 프로세스에서 실행 됨).CreateThread


메모리 관리가 필요한 언어 (예 : C 또는 C ++)를 사용하려는 경우 메모리 할당 API (Windows)의 차이점을 이해하는 것이 매우 중요합니다. IMHO를 설명하는 가장 좋은 방법은 다이어그램을 사용하는 것입니다.

여기에 이미지 설명 입력

이것은 매우 단순화 된 Windows 관련보기입니다.

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.

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.

So what all this means, is that if you try to allocate, say just an 8 byte memory block with 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.

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.)

Using VirtualAlloc incorrectly can lead to severe memory fragmentation.

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:

  • 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.

  • 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.

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

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.

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.

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.)

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

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, raising an exception, etc.

These functions are a recommended way to allocate/free memory and objects if you program in 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.


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.

  • 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

  • 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.


VirtualAlloc ===> sbrk() under UNIX

HeapAlloc ====> malloc() under UNIX


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

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).

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

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).

참고 URL : https://stackoverflow.com/questions/872072/whats-the-differences-between-virtualalloc-and-heapalloc

반응형