## Temporary memory

*tempmem* mainly provides temporary memory for [[cstrings]] but it may also be used for other simple structs without destructor as well.

You get it with

- `tempstr(size)`
- `tempmem(size)`
- `dupstr(cstr)`

It is **not** meant to store strings in a context which outlives the last tempmem save position, e.g. in a global object.

You can copy a temporary cstring into a heap-allocated string (`for delete[]`) using

- `newcopy(cstr)`

**IMPORTANT**: You **must** at a low function level regularly call `purge_tempmem()` or the heap will fill up until you are out of memory!


### Technical description

*tempmem* is a kind of Arena memory, though it's not bound to an object but to a function. Therefore you don't need to pass in an Arena object in every allocation.

It is primarily intended to allow a function to return a cstring. As such it is a 3rd option to the c and the c++ approach:

- c: caller must provide memory to the function. e.g. snprintf().
  disadvantage: caller does not know in advance how much memory is needed and tends to massively over allocate in a local variable increasing the risk of a *stack overflow*.
- c++: strings are always (except very short strings up to 7 chars) allocated on the heap.
  disadvantage: slower, leads rapidly to *heap fragmentation*.


### Purging the tempmem

*tempmem* uses a 'secret' buffer to allocate memory for each new string. This buffer automatically grows and yes, expands into *the heap*.
- disadvantage: without some active precautions you will be out of memory very soon.

Therefore the user must actively purge the tempmem buffer. There are 2 basic tools:

`purge_tempmem();`

This trims the tempmem buffer back to it's last 'save' state. If you haven't defined a save position, the entire buffer (of this core) is purged.
Your application should contain this call at low function level in the main processing loop(s).

`TempMemSave \_;`

An instance of this class creates a tempmem save point in it's constructor and restores (purges) tempmem in it's destructor. Calls to `purge_tempmem()` during it's lifetime will only purge up to the safe position.
Functions which do a lot of string manipulations or which do _some_ string manipulations in a loop, directly or indirectly in called functions, should create a TempMemSave and call purge_tempmem() in the loop. You can even nest them, if that makes sense.


### Returning temp strings from a TempMemSave context

If you want to return a temporary cstring from within a TempMemSave context, you can't do this *directly*. Instead you must copy it over the save position before you can return it:

`return xdupstr(the_string);`

This is also needed to pass the string from a local block with a TempMemSave to an outer local variable of the function. It is needed whenever you pass a string over a TempMemSave position.
Caveat for nested save positions: xdupstr() only skips *one* save position!
Also caveat: for technical reasons _xdupstr() purges the tempmem_ (up to the save position).


### tldr;

This all may sound a little bit tedious, but except for the case where you want to hand out a temporary string accross a save position it is straight forward:

- at a low level regularly call purge_tempmem(). **this is mandatory!**
- functions which (indirectly) allocate high or unknown amount of tempmem should create a save position, preferably in functions which do not return a temporary cstring. __:-)__
- before calling a function which may allocate (too much) tempmem create a save position yourself.

And have a look at the heap: kilipili's [[malloc]] replacement provides a heap dump facility.


















