… DRAFT … lots of postgrad students ask this sort of question. clagged from a ‘9315 question.

Remember that memory allocations have a ‘contract’ around their use – when you request an amount of memory, you promise you will only ever use up to that many bytes beyond the pointer you’re given back, and when you return it, you promise you will never use the pointer again.

Most C environments are rather lax on both of these points, so you’ll be allowed to do that (and entering into the wonderful world of Undefined
Behaviour), often leaving you with weird and subtle bugs. Worse, when
they finally notice you’ve done something wrong, they tend to explode in your face with segfaults or assertion failures that can be some distance from the actual bug.

Tools like AddressSanitizer (which I absolutely love) or Valgrind will tell you exactly what’s going wrong here. Based on what you described, I compiled with AddressSanitizer, and immediately got: