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).
|
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.
|