This is my 2c.
It is correct you cannot check every single line of code for errors. Besides it, not all errors are able to crash the application and not all of them need to stop the program.
In my applications I tend to separate the errors derived from user actions from those coming from programmer actions: while I make all efforts in giving to the first ones good explanations, the second needs to be checked before the application is licenced.
Based on the ErrChk and NullChk macros included in toolbox, I have developed some error checking macros for file I/O, serial communication, DAQ functions and so on which allow me to react on severe errors. For example: a DAQ checking macro that jumps to a fixed label to stop a test execution and another that simply exits with a break statement (useful when included in a loop after which I need to clear the acquisition / generation tasks in progress). In all those macros I included the line of code on error (using the __LINE__ macro) and in case the error must be reported to the operator I format a string with the error code, line and function on error (__FUNCTION__ macro is very useful for this!) and some explanation (obtained with GetGeneralErrorString, GetNIDaqErrorString, GetFmtIOErrorString... functions).
Last item: some time it is not safe to simply break down the code with a MessagePopup (this is when there are motors running or parts live with high current / voltage on them and so on): in this case I have developed a warning function issued with a PostDeferredCall that receives all parameters related to error encountered and finally displays a panel with all these datas or writes them to a file after the application has safely ended the test in progress.
Finally, I'm sorry for not having answered to your question before but I missed it. I find sharing our programming tips is very useful, so everyone which will comment this or add his suggestions will be well accepted.