# free

Definition: | free(object addr) -- or -- addr = free(object addr) -- via ffree(), see technicalia
Description: | Free up a previously allocated block of memory by specifying the address of the start of the block, ie/eg as returned by allocate(). The addr parameter can also be a sequence of such atoms, which are released in turn. It may also be NULL or contain NULLs, which is/are politely ignored.
pwa/p2js: | Not supported
Comments: | Use free() to recycle blocks of memory during execution. This reduces the chance of running out of memory or getting into excessive virtual memory swapping to disk. Do not reference a block of memory that has been freed, or attempt to free() it more than once. In some (/many/most) cases it may help to deliberately zero the variable passed to the addr parameter immediately after free() returns, as per the second invocation method above. If a delete_routine() is in force for addr, then the call to free() behaves as a call to delete(). It is assumed that will re-invoke free(), but with the internal delete_routine field zeroed, and by that I mean that the routine passed to delete_routine() explicitly invokes free(), rather than that aspect being somehow automatic (and/or somehow avoiding a double-free error). When a program terminates, all allocated memory is returned to the system. Strictly speaking it is not necessary to release "one-off" allocations, and many legacy programs will not, however they may appear in the final report should memory leak checking be enabled (see technicalia).
Example: | demo\rosetta\Count_examples.exw
Implementation: | Partly in builtins\pAlloc.e (an autoinclude), but mainly via :%pFree 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: | allocate
Technicalia | free() is a procedure that does not return a value. There is a matching function, ffree(), also defined in builtins\pAlloc.e that returns appropriate NULLs, ie ffree(a) returns NULL and ffree({a,b,c}) returns {NULL,NULL,NULL} [whether or not they were NULL to begin with]. For convenience, the front-end maps free() to ffree() rather than issue a compilation error. This allows eg `a = free(a)`, in line with mpz_free(), and reduces the chance of inadvertently referencing/modifying freed memory allocations. Obviously you are at liberty to explicitly invoke ffree(), just not as a procedure call. There is an experimental (ie unfinished) memory leak checker built into the interpreter. At the top of p.exw, you should find the constant MCHK = 0|1. This flag directly controls whether, later on in the same file, it creates a new stack/heap, calls :%RunCleanup, then restores the original stack/heap and finally invokes check_heap(), which can be found in builtins\VM\pMemChk.e and creates C:\Program Files (x86)\Phix\memchk.txt before blurting out a copy of that file on screen if the number of errors detected is not 0. At the moment this only occurs for interpreted programs, and only if there is no trace or profile occurring. Compiled programs would need to do the inverse, ie run the app, cleanup, then create a new stack/heap for check_heap. Since trace/profile are part of p.exe yet get invoked from within the running app, ending up with a clean empty stack/heap is unlikely, which is why I originally disabled the check when such occur. I may be wrong and it may all be perfectly fine anyway, but I simply have not bothered to try it. Further, builtins\VM\pcfunc.e has to invoke builtins\VM\pStack.e\:%SetCCleanup to stop any call_backs etc from being recorded as memory leaks, and there is quite a bit of fiddly code in builtins\VM\pStack.e affecting the behaviour of :%opAbort. Currently, when MCHK=1, interpretive self-hosting is quite broken (eg/ie "p p -test"), and I would hazard a guess that is mainly down to the new code in pStack.e - actually, I take that back, I now see that "p p -test" is (slightly less, but still) broken when MCHK=0... It is not yet possible to skip checks on :%pAlloc items that have not been :%pFree’d, ie/eg a constant x = allocate(n) will be reported as a memory leak unless you explicitly free(x) somewhere, and specifically the l_MyAllocate() calls in win32lib\w32support.e, and the whole of win32lib in general have not yet been addressed and are unlikely to be any time soon. However all the demos for arwen and tinewg as included in the package, along with Edita and Phix itself have been tested, but almost all other legacy code run under MCHK=1 will most likely report errors. Generally speaking, with the above mentioned exception of l_MyAllocate, most leaks reported in memchk.txt are quite trivial to resolve. As an example, arwen.ew now has free(LVI/LV/lf/ TVI/TVIS) at the end of WinMain(), as fairly obviously the five lines where those items were allocated were reported as culprits in said error log. Enabling/disabling the memory leak checking could hardly be simpler: just change the MCHK setting and run "p -cp". The division between pAlloc.e and pHeap.e exists so that delete_routine() can be used in the former.