Say I have a big block of mapped memory I finished using. It came from mmaping anonymous memory or using MAP_PRIVATE. I could munmap it, then have malloc mmap again the next time I make a big enough allocation.
Could I instead give the memory to malloc directly? Could I say "Hey malloc, here's an address range I mapped. Go use it for heap space. Feel free to mprotect, mremap, or even munmap it as you wish."?
I'm using glibc on linux.
glibc malloc calls __morecore (a function pointer) to obtain more memory. See <malloc.h>. However, this will not work in general because the implementation assumes that the function behaves like sbrk and returns memory from a single, larger memory region. In practice, with glibc malloc, the only realistic way to make memory available for reuse by malloc is calling munmap.
Other malloc implementations allow donating memory (in some cases as internal interfaces). For example, musl's malloc has a function called __malloc_donate which should do what you are asking for.
Related
As I know, heaps such as malloc is stored in dynamic data. But is it right to say
that malloc function call may allocate the memory space in stack area?
malloc is not a feature of MARS or QtSpim.
There is a system call, #9, that mimics *nix sbrk, to allocate additional address space to the simulated process. It returns to you the next address available past the global data (and past any prior sbrk's). (However, it only allocates, and does not return memory the way a proper sbrk would do given a negative value.) Another name for this area of memory is heap / heap memory.
It does not allocate stack space as that is in substantially higher in the address space. On these simulators, the stack is limited to about 4MB, and the memory returned by sbrk does not reach anywhere near into that 4MB.
Heap memory is useful since a heap allocated memory will survive a function call — a function can return data in the heap but cannot return newly allocated data in the stack, since, by definition, a function that allocates stack space must release that exact same amount when it leaves.
Stack space is allocated simply by decrementing the stack pointer (and released by incrementing the stack pointer). By convention, all functions & subroutines agree to leave existing stack memory alone and allocate new stack memory if they want it, though they also must release it before returning to their caller. When those restrictions do not meet requirements, heap memory is a good choice. Global data is also an option for memory that survives a function call, though that can lead to problems with multithreading (and potentially with recursion).
According to this OCaml's memory is contained in two contiguous chunks of virtual memory managed by the OCaml runtime. I would like to know why this is necessary. Couldn't OCaml simply use the system malloc to allocate memory, and only use these heaps to store the block headers and pointers to the object's actual home in memory? This seems like a reinvention of the wheel when the operating system can do so much of the work instead.
I would also like to know why OCaml must allocate an entirely new major heap during the compact phase of garbage collection (source here), e.g.:
In the following rough sketch, let the letters A-D represent equally-sized pieces of OCaml blocks, and let . represent a freed space of the same size. From what I am given to understand, the OCaml garbage collector would "compact" this major heap:
[AAABB..CCCCCC.....DDD....]
By allocating a new major heap:
[.........................]
And copying the still-live blocks into it, before freeing the original heap:
[AAABBCCCCCCDDD...........]
How is this more efficient than simply rearranging those blocks inside the original heap? In the example above, a contiguity check could have avoided having to move blocks A and B at all, and in any case, how is it more efficient to ask the operating system to always allocate an entire new major heap?
Every garbage collector handle their own heap for performance reasons. malloc is a quite slow, and compared to OCaml minor heap allocation it is multiple orders of magnitude slower (an allocation in the minor heap is done in 2 assembly instructions).
For the compaction, no that doesn't reallocate.
I am trying to find some useful information on the malloc function.
when I call this function it allocates memory dynamically. it returns the pointer (e.g. the address) to the beginning of the allocated memory.
the questions:
how the returned address is used in order to read/write into the allocated memory block (using inderect addressing registers or how?)
if it is not possible to allocate a block of memory it returns NULL. what is NULL in terms of hardware?
in order to allocate memory in heap we need to know which memory parts are occupied. where this information (about the occupied memory) is stored (if for example we use a small risc microcontroller)?
Q3 The usual way that heaps are managed are through a linked list. In the simplest case, the malloc function retains a pointer to the first free-space block in the heap, and each free-space block has a header that points to the next free space block in the heap. So the heap is in-effect self-defining in terms of knowing what is not occupied (and by inference what is therefore occupied); this minimizes the amount of overhead RAM needed to manage the heap.
When new space is needed via a malloc call, a large enough free-space block is found by traversing the linked list. That found free-space block is given to the malloc caller (with a small hidden header), and if needed a smaller free-space block is inserted into the linked list with any residual space between the original free space block and how much memory the malloc call asked for.
When a heap block is released by the application, its block is just formatted with the linked-list header, and added to the linked list, usually with some extra logic to combine consecutive free-space blocks into one larger free-space block.
Debugging versions of malloc usually do more, including retaining linked-lists of the allocated areas too, "guard zones" around the allocated heap areas to help detect memory overflows, etc. These take up extra heap space (making the heap effectively smaller in terms of usable space for the applications), but are extremely helpful when debugging.
Q2 A NULL pointer is effectively just a zero, which if used attempts to access memory starting at location 0 of RAM, which is almost always reserved memory of the OS. This is the cause of a significant quantity of memory violation aborts, all caused by programmer's lack of error checking for NULL returns from functions that allocate memory).
Because accessing memory location 0 by a non-OS application is never what is wanted, most hardware aborts any attempt to access location 0 by non-OS software. Even with page mapping such that the applications memory space (including location 0) is never mapped to real RAM location 0, since NULL is always zero, most CPUs will still abort attempts to access location 0 on the assumption that this is an access via a pointer that contains NULL.
Given your RISC processor, you will need to read its documentation to see how it handles attempts to access memory location 0.
Q1 There are many high-level language ways to use allocated memory, primarily through pointers, strings, and arrays.
In terms of assembly language and the hardware itself, the allocated heap block address just gets put into a register that is being used for memory indirection. You will need to see how that is handled in the RISC processor. However if you use C or C++ or such higher level language, then you don't need to worry about registers; the compiler handles all that.
Since you are using malloc, can we assume you are using C?
If so, you assign the result to a pointer variable, then you can access the memory by referencing through the variable. You don't really know how this is implemented in assembly. That depends on CPU you are using. malloc return 0 if it fails. Since usually NULL is defined as 0, you can test for NULL. You don't care how malloc tracks the free memory. If you really need this information, you should look at the source in glibc/malloc available on the net
char * c = malloc(10); // allocate 10 bytes
if (c == NULL)
// handle error case
else
*c = 'a' // write a in the first character on the block
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.
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);
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.
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.
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.
I know I can reserve virtual memory using VirtualAlloc.
e.g. I can claim 1GB of virtual memory and then call in the first MB of that to put my a growing array into.
When the array grows beyond 1MB I call in the 2nd MB and so on.
This way I don't need to move the array around in memory when it grows, it just stays in place and the Intel/AMD virtual memory manager takes care of my problems.
However does FastMM support this structure, so I don't have to do my own memory management?
Pseudo code:
type
PBigarray = ^TBigarray;
TBigArray = array[0..0] of SomeRecord;
....
begin
VirtualMem:= FastMM.ReserveVirtualMemory(1GB);
PBigArray:= FastMM.ClaimPhysicalMemory(VirtualMem, 1MB);
....
procedure GrowBigArray
begin
FastMM.ClaimMorePhysicalMemory(PBigArray, 1MB {extra});
//will generate OOM exception when claim exceeds 1GB
Does FastMM support this?
No, FastMM4 (as of the latest version I looked at) does not explicitly support this. It's really not a functionality you would expect in a general purpose memory manager as it's trivially simple to do with VirtualAlloc calls.
NexusMM4 (which is part of NexusDB) does something that gives you a similar result, but without wasting all the address space before it is needed in the background.
If you make an initial large allocation (directly via GetMem, or indirectly via a dynamic array or such) the memory is allocated in just the size needed, via VirtualAlloc.
But if that allocation is then resized to a larger size, NexusMM will use a different way to allocate memory which allows it to simply unmap the allocation from the address space an remap it again, at a larger size, when further reallocs takes place.
This prevents the 2 major problems that most general purpose memory managers have when reallocating:
during a normal realloc the existing and new allocation need to be present in the address space at the same time, temporarily doubling the address space and physical memory requirements
during a normal realloc, the whole contents of the existing allocation needs to be copied
So with NexusMM you would get all the advantages of what you showed in your pseudo code (with the exception that the first realloc will involve a copy, and that growing your array might change it's address) by simply using normal GetMem/ReallocMem/FreeMem calls.