How to create and free dynamic arrays with Arduino

On AVR board there is some protection against stack overflowing INTO the heap. The memory allocate always ensures there is at least 128bytes left available for stack use. (see the examples in Taming Arduino Strings ) This is one of the things that makes using Strings on AVR boards so safe. Strings also automatically protect against overallocation of the heap without causing your program to crash.

The AVR (and others) memory manager also coalesces adjacent empty fragments to improve reuse.
The managing arduino memory reference talks about memory corruption, but that is not possible on AVR boards UNLESS you try and allocate more then 128bytes of stack in method call.

Memory corruption is possible (and happens) on ESP2866 and ESP23 boards which do not have the 128byte stack buffer.

Allocating lots of small Strings when combined with returning Strings from functions does product memory fragmentation. ESP boards have a 12 char[ ] build into their String class which they use for 'small' Strings to avoid allocating memory on the heap for small Strings.

So in summary, dynamic memory allocation on AVR boards is 'safe' if you ALWAYS check the return and handle out-of-memory AND don't use more then 128bytes of local stack in your methods (including arguments).

Freeing memory after you are finished with it (and not before) will make your memory go further.

The biggest problem (in my mind) using dynamic memory allocation is what to do if/when your program runs out of memory. How does your program recover? The Arduino String library just returns an empty String and keeps going. Your program won't crash but the logic may be screwy.
Using your own dynamic memory, your program has to cope with null pointers in some 'safe' way. This tends to lead to a lot of is pointer null checks.