It is undefined behaviour to access allocated memory beyond its end. In other words, it may crash your application or may work for years as expected.
malloc()
typically allocates memory in multiples of minimum alignment sizeof(void*)
, so that sometimes you can access a few bytes past the required size with no negative consequences.
A couple of notable examples of undefined behaviour related to heap memory going unnoticed for years:
The poisoned NUL byte, 2014 edition:
An odd malloc() size will always result in an off-by-one off the end being harmless, due to malloc() minimum alignment being sizeof(void*).
How Microsoft Lost the API War:
I first heard about this from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it.