Checking the specification against the code is also hard. A program can't usually do the job without some human help. When the two don't match, it's very hard to figure out what's wrong. Even if system is verified, doesn't help handle hardware failures or other unexpected things that weren't part of the specification. When the system is designed, must try to predict the kinds of errors that might occur, and build in ways of detecting them.
Free blocks hold management information.
Don't store vital information at the beginning of blocks, since this is the area that will be destroyed first. This can be used to catch memory overruns, and misuse of information. Magic values also work well for disk blocks. Remember who memory was given to, make sure it is that party that returns it. Operating systems are very hard to get completely debugged, so internal checks like this are a great help.