# allocate

Definition: | atom pMem = allocate(integer i, bool cleanup=false) -- or -- atom pMem = allocate_word(atom v=0, bool cleanup=false, integer size=machine_word())
Description: | Allocate i or size bytes of memory and return the address, or 0 (aka NULL) on failure. The address returned is always machine_word aligned.
pwa/p2js: | Not supported.
Comments: | If the optional cleanup flag is true (/non-zero), the memory will be automatically released once it is no longer required, otherwise the application should invoke free() manually. Note that you should avoid invoking free() or delete() on pMem when cleanup is true - if nothing else that would explictly invalidate the implicit safety guarantees it provided, and in some cases open the door to unpredictable memory corruption, should there still be a reference to some memory that you have just explicitly said (by invoking said) can now be used for something else (and o/c that whole tribe of potential problems is ever-present when cleanup is false). In an ideal world the cleanup flag should probably default to true, however that causes far too many problems with legacy code. (Somewhere beneath the calm waters of the lake my little feet are paddling away furiously...) The allocate_word() function allocates a single block of size bytes of memory (must be 1/2/4/8) and sets it to (machine integer) v. Obviously v is defined as atom to allow full 32/64 bit values outside the usual 31/63 bit range, and the same caveats apply as explained in detail in peek() and poke() when using a size of 8 on a 32-bit architecture. The peekns/peeknu/poken() routines are natural companions to allocate_word().
Example: |
    buffer = allocate(100)
    -- (mem_set(buffer,0,100) could be used instead of the following)
    for i=0 to 99 do
        poke(buffer+i, 0)
    end for
Implementation: | Partly in builtins\pAlloc.e (an autoinclude), but mainly via :%pAlloc in builtins\VM\pHeap.e (also an autoinclude) - be warned however it is low-level complicated stuff that you do not need to know.
See Also: | free, mem_set, peek, poke, call, delete_routine
Technicalia | Euphoria allows say allocate(107.5) and provisions 107 or 108 bytes as it sees fit, whereas in Phix the programmer is forced to explicitly round non-integers in the required direction before invoking allocate(). Technically the first parameter is an atom, to allow values above #3FFFFFFF (on 32-bit, though a hard limit of #5FFFFFF8 applies, whereas 63-bit integers will exceed available hardware for decades yet), but it is explicitly checked to be an exact and non-negative integer (see builtins\pAlloc.e for details). Certain algorithms are simplified by permitting allocate(0). However the application had better not try and use that memory, and unless the flag for automatically doing so has been used it still has to remember to free() it. In practice, allocate(0) will yield 12 or 20 bytes of useable memory on 32/64 bit systems respectively, not that I recommend relying on that. A minor point is that technically allocate() on 32-bit yields an unsigned address whereas on 64-bit it is treated as signed, though that is only likely to have any effect should there be some strange OS-level address mapping going on. As explained in builtins\VM\pHeap.e, 32-bit Phix deliberately limits allocations to 1,610,612,728 bytes (8 bytes shy of #60000000) whereas in tests 32-bit Euphoria managed 1,873,463,796 (#6FAAC9F4) bytes; it is assumed this will not be an issue for any sensibly-written application. In any case, the ability of 32-bit Phix to construct (hll) strings up to 1,610,612,711 characters compared to the 32-bit Euphoria (hll) sequence limit of a mere 468,365,949 elements(/characters) is considered to be completely exhonorating here. Similar limits are theoretically present in 64-bit versions but significantly in excess of any machine that could physically be constructed. The division between pAlloc.e and pHeap.e exists mainly so that delete_routine() can be used in the former. Note that explicit calls to free() may be measureably faster than relying on cleanup, simply because the former (static call) can for instance allocate stack space directly whereas the latter (dynamic call) must examine the appropriate symtab entry and calculate the needed stack space. (And, yes, a free() call must itself allocate and free some small bit of memory, albeit not recursively, mainly for a return address.) However code is typically much cleaner with automatic cleanup, it is not worth obsessing over unless there are millions of dynamic free() calls, and even a single test to see whether a manual free() is needed could easily tip the balance back in favour (performancewise) of automatic.