`free' allocated buffers only on success inside the main loop, and `free' them on error inside their respective functions (fixes an UB where an already freed buffer is freed again in the main loop)
set next byte of ID to zero each time a new character is appended to prevent undefined behaviours.