How can I protect a microcontroller from memory corruption due to buffer overruns?
"Canary bytes" are a known thing.  Write an easily recognizable byte pattern between data structures, and if those bytes ever change, then something has gone wrong.  But it will never tell you when it went wrong or why.  You just know that you have buggy code.

Much better is to write the code so that it doesn't cause buffer overflows in the first place.  Check all your buffers are big enough.  When reading bytes from elsewhere, only accept as many bytes as you can handle, especially if something else is telling you how many bytes to expect.  Look carefully at data concatenation, usually string concatenation.  Is the destination buffer always big enough to hold the result?

Stack overflow is another thing that can cause unpredictable effects.  On small systems, it's likely to be either too many nested function calls, or else too many, or too large, local variables within the functions.