One way to summarize your good post is in engineering there is no simple generic testing. There is testing to reduce mfgr mistakes. There is testing against outside opposition ranging from UI data entry errors to active attackers. There is testing to make a program as defensible as possible. There are other classes of testing too. And some testing strategies are not compatible with each other or compatible with the shipped operating environment.

So for mfgr mistake code testing you find a problem you give up or set the board on fire or anything to make sure it never gets shipped to a customer. That's not good for a spaceship or a nuclear reactor.

For outside opposition you can assume a non-zero BER on the telecom link either due to signal issues or radiation (acute or long term degradation) in the analog circuitry. However anti-attacker code is just a place to get flipped bits and crash. On the other hand a really naive string copier looking for a null with a flipped bit will never terminate, but you're watching memory address bounds anyway, so ...

The right thing for a desktop computer to do when the stack pointer or PC gets lost is to run off into outerspace and get powned or panic the system because who cares that should never happen on a shipped system on earth in a non-critical application. The right thing for an outerspace vehicle is populate "unused" memory with a jump to a recovery routine.

going off on a tangent related to your post:

Simplicate and add lightness. Interrupts exist because slow 1970s era processor tech couldn't keep up with 1970s IO tech or UI. In 2016 you poll. Your interrupt service routine can't get corrupt if you don't use one. Your "interrupts enabled" bit can't get cleared if you're not using it. Your stack pointer can't get lost if you don't use one. If you need to repoint the antenna every couple minutes and your program crashes every couple hours on random average, you power it up every couple minutes for a few seconds and then it can't crash or lock up when there's no power. Loops exist because in 1977 when we had 128 bytes of memory and wanted to load 8 bytes of data its cheaper in terms of memory to write a loop that reads one byte 8 times, but in 2016 you unroll all loops so if there's a single bit error in one read then "most of" the process works and a single bit error in the loop code can't crash it because there's no loop code. You're paying the mfgr for great gobs of memory in 2016, use it. From an engineering standpoint its like replacing crane mounting bolts the size of bratwursts with 6-32 sized hardware from walmart because thats how we rolled in 1977 and ain't nothin gonna change that and at least sometimes in desktop simulation it works.

The stackoverflow article displays perfectly why I don't use stackoverflow. 90% of the comments are people talking about how the problem is no fun, weird assumptions about the asker, blind cargo-cult style devotion to paperwork and tradition and passing the buck to other agencies, or complaining (incorrectly) that if its not perfectly solvable then no effort should be made. If you want to know the option flag to sort the output of GNU ls by modification time, then SO works, but SO is useless for all serious questions. SO is great at answering the questions I don't need to ask and sucks at answering the questions I need answered.