Im working win HeapAlloc. When i create the heap handle and then allocate memory with HeapAlloc is it necesary that the next call to HeapAlloc allocates the byte following the previous call of the function?

I need dinamically create memory that has to be contiguos, so how do i do?
Posted on 2004-04-02 00:11:46 by Ateneo
I am not sure that HeapAlloc will gaurantee contiguous memory. You can use VirtualAlloc to do that by passing the address of the start of the next block in the function.

; Reserve the maximum amount of memory to use

invoke VirtualAlloc, NULL, MAX_MEM, MEM_RESERVE, PAGE_READWRITE
mov [pBase],eax
; The pNext is initially set to the base pointer of the reserved memory
mov [pNext],eax

; allocations use the next contiguous byte as the start address
invoke VirtualAlloc, [pNext], [cbAlloc], MEM_COMMIT, PAGE_READWRITE
add eax,[cbBuffer]
mov [pNext],eax


The size of the buffer should be a multiple of the page size obtained from GetSystemInfo :

invoke GetSystemInfo, offset SysInfo

mov eax,SysInfo.dwPageSize
mov ecx,[nPages_per_block]
mul ecx
mov [cbAlloc],eax
Posted on 2004-04-02 01:08:04 by donkey
You can use HeapReAlloc to change the size and/or other parameters of the previosly allocated block. Of course, newly allocated block will be contiguous in virtual address space. If you specify larger size for reallocation, windows will try to give you a larger block at the same address. If windows fails to do that, it will move previosly allocated block to another location with more free space available. You can prevent moving by specifying a HEAP_REALLOC_IN_PLACE_ONLY flag. See MSDN for details.
Posted on 2004-04-02 01:38:54 by Vaxon
HeapAlloc is fine for dynamic growth. You cannot depend on subsequent HeapAlloc's to follow the latest allocation (most of the time they will, but if you have done some HeapFree's, space can be fragmented, and old slots will be reused).

The trick is of course to use HeapReAlloc. To avoid moving the block on every reallocation, it's a good idea to use "delta growth". So, when you need to expand your memory block, don't add space for a single entry - grow in blocks. The amount to grow will vary depending on data item size and usage patterns, so experiment a bit.

Donkey's approach is fine if you don't mind every allocation being rounded up to page size (4k on almost all current machines). Do note, however, that you will only be guaranteed linearity if you (and code you call) don't do other VirtualAlloc calls - but you should generally be safe.

For really large allocs, VirtualAlloc is probably the best bet anyway - there's some performance problems on 9x with very large heap blocks, besides VirtualAlloc is pretty flexible - page protection flags, lets you commit/decommit pages at will (decommitted pages means you're not taking physical memory, but the address range is still reserved for your use).
Posted on 2004-04-02 06:59:42 by f0dder
If you know the "maximum" amount of memory your code will use, you can use the VirtualAlloc with MEM_RESERVE. You can do this with almost as much as you need, even 1GB without a performance hit (memory usage dependant). Windows will "reserve" this amount of continuous memory, so a VitualAlloc or HeapAlloc won't allocate memory within your block. Then do continuous VirtualAlloc calls with MEM_COMMIT as needed! And you're guaranteed that there will be no fragmentation or reallocation. Also, VitualAlloc performance is "kick-ass!" fast (for most memory allocation needs!)! Since even HeapAlloc uses it at a lower level! For small, fragmentable allocations, HeapAlloc is preferable to me!

Regards!
Posted on 2004-04-02 07:57:57 by SubEvil
Afaik, HeapAlloc doesn't use VirtualAlloc internally - on NT it calls ntdll.RtlAllocateHeap. It probably does end up using the same allocation primitive as VirtualAlloc, but that's "somewhere down the call chain" in kernel mode :)
Posted on 2004-04-02 08:08:01 by f0dder