Allocate a byte array and free it afterwards in delphi
Asked Answered
I

4

5

I would like to allocate space (dynamic size) with a byte array and get a pointer to the "spacearea" and free it later if I don't need it anymore.

I know about VirtualAlloc, VirutalAllocEx and LocalAlloc. Which one is the best and how can I free the memory afterwards?

Thank you for your help.

Insufflate answered 3/8, 2012 at 12:51 Comment(2)
Could you explain what is wrong with GetMem?Dhiman
Never thought of getmem. sorry about that.Insufflate
W
13

I don't think it is a good idea to use the winapi for that instead of the native Pascal functions.

You can simply define an array of bytes as

var yourarray: array of byte;

then it can be allocated by

setlength(yourarray, yoursize);

and freed by

setlength(yourarray, 0);

Such an array is reference counted and you can access individual bytes as yourarray[byteid]

Or if you really want pointers, you can use:

var p: pointer;

GetMem(p, yoursize);

FreeMem(p);
Wheelock answered 3/8, 2012 at 12:57 Comment(2)
This would work. But I forgot to mention that I need the pointer/space for GLOBAL purposes. If a function, procedure leaves/returns, the stack gets flushed?!Insufflate
@BenjaminWeiss Both dynamic arrays and GetMem/FreeMem are allocated on the heap, not on the stack, so are available unless they are out of scope (for dynamic arrays), or explicitly freed (pointers).Zitazitah
Z
5

You should better use GetMem/FreeMem or a dynamic array, or a RawByteString. Note that GetMem/FreeMem, dynamic arrays or RawByteString uses the heap, not the stack for its allocation.

There is no interest about using VirtualAlloc/VirtualFree instead of GetMem/FreeMem. For big blocks, the memory manager (which implements the heap) will call VirtualAlloc/VirtualFree APIs, but for smaller blocks, it will be more optimized to rely on the heap.

Since VirtualAlloc/VirtualFree is local to the current process, the only interest to use it is if you want to create some memory block able to execute code, e.g. for creating some stubbing wrappers of classes or interfaces, via their VirtualAllocEx/VirtualFreeEx APIs (but I doubt it is your need).

If you want to use some memory global to all processes/programs, you have GlobalAlloc/GlobalFree API calls at hand.

Zitazitah answered 3/8, 2012 at 13:25 Comment(0)
H
2

VirtualAlloc is a page allocation function. It is the low level user space code function for allocating memory. But you must understand that the memory returned from VirtualAlloc is aligned to a multiple of the page size.

On windows 32 bit the page size is normally 4096 Bytes. On other systems it might be larger.

So this makes VirtualAlloc useful when you need whole pages of memory. VirtualAlloc can allocate large "ranges of pages". The pages are virtual and are thus actually mappings to underlying system RAM and half the time are swapped out to the swap file, and this is why it is called VirtualAlloc, emphasis on virtual.

Using VirtualAlloc and VirtualAllocEx you can also just reserve some pages of memory. Reserved pages are a range that are held in reserved state until you are sure they will be used, at which point you can commit the pages, at which time the underlying resources needed for the pages will be allocated/committed.

Use VirtualFree to free the pages you allocated or reserved with VirtualAlloc.

The difference between VirtualAlloc and LocalAlloc is that LocalAlloc allocates from a heap, and a heap is a mechanism of allocating blocks of memory from much larger blocks of reserved pages. Internally, a heap allocates large sections of memory using VirtualAlloc, and then divides those pages up into smaller blocks that you see as buffers returned from functions like malloc, getmem and LocalAlloc.

LocalAlloc could be though of as the Windows built in version of malloc or getmem. A call to LocalAlloc is similar to calling malloc in C++ or to calling getmem in Delphi. In fact you could override the GetMem in Delphi and use LocalAlloc and your DElphi application will probably just run the same.

Call LocalFree to free some memory allocated with LocalAlloc. Internally this will mark the block of memory as available to the next caller.

So the main consideration now when deciding is on overhead. If you need to allocate often then you should use LocalAlloc or getmem, because committing and reserving virtual pages is a more time consuming process.

In other words, use getmem or LocalAlloc unless you have a very special reason not to.

In all my tests with Delphi 5 versus C++ compilers the Delphi 5 getmem was faster, although that was five years ago. Since then allocators like hoard are available that might be faster. But it is hard to say what is faster when there are so many variables.

But for sure all the heap functions like LocalAlloc, malloc and getmem should be much faster than allocating and freeing with VirtualAlloc, which is normally used to reserve memory internally for heap functions like LocalAlloc and getmem.

For Pascal programs, prefer getmem or SetLength because this is more portable. Or you can write your own wrapper function to LocalAlloc or whatever the OS heap function is.

Humfried answered 12/9, 2012 at 19:35 Comment(0)
R
1

The functions that you have listed are WinAPI functions, which are platform dependant. Obviously you should use the functions of the same API for deallocating that you have used for allocation.

If you want to use Delphi memory manager, than GetMemory and FreeMemory is the obvious choice, however if you need your pointer to be aligned to the system page size(which is requirement for some low level libraries) or you are going to use large buffer sizes, then Windows API virtual memory functions VirtualAlloc and VirtualFree are your best friends.

Reckoning answered 3/8, 2012 at 13:0 Comment(4)
Thank you. VirtualFree was what I was looking for too.Insufflate
Use GetMem/FreeMem, there is no GetMemory/FreeMemory functions. And for larger blocks, GetMem will call VirtualAlloc: so there is no benefit of calling directly VirtualAlloc/VirtualFree here. Only add confusion.Zitazitah
@ArnaudBouchez What you are saying is true for the default memory manager.The benefit of the VirtualAlloc is that you can be sure that the pages are aligned to page size, as for the GetMem behavior, you can't know the buffer sizes because it is possible to switch between different memory managers in Delphi and they can use another allocation policies.Reckoning
@BorisTreukhov But the OP did not ask for aligned memory, just for allocating a memory buffer. And it is pretty easy to align a buffer returned by GetMem (e.g. allocated 15 bytes more and align to closest 16 bytes boundary), or just set FastMM4 to serve only aligned blocks, by setting the Align16Bytes compilation option.Zitazitah

© 2022 - 2024 — McMap. All rights reserved.