블로그 이미지
대갈장군

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

Notice

2011. 3. 11. 23:54 프로그래밍/Windows API
윈도우에서 메모리를 할당하는 다음 방법은 VirtualAlloc() 함수다. 이 함수는 malloc 함수에서 보다 발전된 형태로 사용자에게 여러 가지 추가 기능을 제공한다.

가장 큰 차이점은 '예약'과 '확정' 상태가 존재한다는 것인데 malloc의 경우 '확정' 상태만 있었다. 여기에 예약이 추가 되었는데 이로써 보다 효율적인 메모리 사용이 가능해 졌다. 예약만 한 경우 물리적 메모리는 전혀 소모되지 않는다. 오직 확정에만 가상 메모리가 실제로 할당된다.

함수의 원형은 다음과 같다.
LPVOID WINAPI VirtualAlloc( __in_opt  LPVOID lpAddress, __in      SIZE_T dwSize, __in      DWORD flAllocationType, __in      DWORD flProtect );

첫번째 인자가 할당하고자 하는 주소의 위치 (4GB의 프로세스 주소 공간에서), 두번째 인자는 할당할 크기, 세번째 인자는 할당 타입인데 바로 여기서 확정, 예약, 높은 번지 할당등을 설정할 수 있다. 자세한 내용은 다음 표 참조. 마지막 인자는 할당할 페이지의 엑세스 타입 설정을 하는데 이것도 malloc과의 다른점 중에 하나다. 읽기 쓰기 접근 제한 설정이 가능하다.

ValueMeaning
MEM_COMMIT
0x1000

Allocates physical storage in memory or in the paging file on disk for the specified reserved memory pages. The function initializes the memory to zero.

To reserve and commit pages in one step, call VirtualAlloc with MEM_COMMIT | MEM_RESERVE.

The function fails if you attempt to commit a page that has not been reserved. The resulting error code is ERROR_INVALID_ADDRESS.

An attempt to commit a page that is already committed does not cause the function to fail. This means that you can commit pages without first determining the current commitment state of each page.

MEM_RESERVE
0x2000

Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.

You can commit reserved pages in subsequent calls to the VirtualAlloc function. To reserve and commit pages in one step, call VirtualAlloc with MEM_COMMIT | MEM_RESERVE.

Other memory allocation functions, such as malloc and LocalAlloc, cannot use a reserved range of memory until it is released.

MEM_RESET
0x80000

Indicates that data in the memory range specified by lpAddress and dwSize is no longer of interest. The pages should not be read from or written to the paging file. However, the memory block will be used again later, so it should not be decommitted. This value cannot be used with any other value.

Using this value does not guarantee that the range operated on with MEM_RESET will contain zeroes. If you want the range to contain zeroes, decommit the memory and then recommit it.

When you specify MEM_RESET, the VirtualAlloc function ignores the value offlProtect. However, you must still set flProtect to a valid protection value, such as PAGE_NOACCESS.

VirtualAlloc returns an error if you use MEM_RESET and the range of memory is mapped to a file. A shared view is only acceptable if it is mapped to a paging file.

간단한 예를 보면, 


ptr = (int *)VirtualAlloc(NULL, sizeof(int)*10, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
VirtualFree(ptr, sizeof(int)*10,MEM_DECOMMIT);
VirtualFree(ptr, 0, MEM_RELEASE);
VirtualFree에 대한 설명이 빠졌는데 메모리 해제 함수다. MEM_DECOMMIT은 확정 해제, MEM_RELEASE는 예약 해제다. 메모리 할당도 MEM_RESERVE와 MEM_COMMIT를 같이 불러 호출하거나 따로 각각 두번 호출해야 한다. malloc보다 좀 번거롭긴 하다.

예약을 할 수 있다는 차이점 이외에도 할당 단위의 차이가 있다. 일단 일반적인 컴퓨터를 기준으로 봤을때 4K 사이즈로 할당이 이루어 진다. 즉, 내가 10K 할당을 요구하면 4의 배수인 12K로 할당한다는 말. 그리고 할당을 시작하는 할당 단위가 있다. 보통의 경우 64K 단위로써 매우 큰 편이다. 즉, 작은 사이즈의 메모리를 여러번 반복적으로 할당하게 되면 할당을 시작하는 단위를 64K로 끊기 때문에 메모리의 조각화가 심해진다. 

그래서 작은 메모리의 할당에는 malloc이 훨씬 더 경제적이다. 그런 경우에는 다음에 알아볼 힙을 사용하는 것도 좋은 방법이다. 

VirtualAlloc의 다른 재미있는 점은 접근 권한 설정이 가능하다는 점인데 너무 보안에 신경을 쓴게 아닌가 싶다.. ㅡ.ㅡ 또 다른 한가지 흥미로운 점은 메모리 잠금 기능인데 할당된 메모리를 물리적 RAM에 상주 하도록 잠그는 함수다. 이로써 보다 빠른 접근 속도를 제공하는데 잘못 사용하면 사용가능한 물리적 RAM을 제한함으로써 운영체제 전체에 속도저하를 유발할 수 있다. 

내가 봤을때 마이크로 소프트에서 야심차게 내놓은 메모리 할당 / 해제 함수인 것 같은데 소규모 프로그램 개발자에게는 그닥 매력적이지 않다. 물론 가능한 기능들은 malloc에 비해서 많고 예약과 확정이라는 효율적인 메커니즘을 제공하기는 하지만 작은 용량을 가지는 다수의 메모리를 반복적으로 할당해야 하는 경우 VirtualAlloc은 메모리 낭비가 너무 심히다.



'프로그래밍 > Windows API' 카테고리의 다른 글

윈도우 메모리 파이널!  (0) 2011.03.12
윈도우 메모리 - 4 (힙과 메모리 맵)  (0) 2011.03.12
윈도우 메모리 - 2 (malloc 함수)  (2) 2011.03.11
윈도우 메모리 - 1  (0) 2011.03.10
윈도우 - 차일드, 팝업  (0) 2009.11.17
posted by 대갈장군