Re: use assert and defensive together



Malcolm McLean wrote, On 24/09/08 23:08:

"Flash Gordon" <smap@xxxxxxxxxxxxxxxxx> wrote in message news:s9iqq5xpvi.ln2@xxxxxxxxxxxxxxxxxxxxxxxxxx
Malcolm McLean wrote, On 24/09/08 10:42:
The exception is when no back-up can be available, in which case defensive programming is appropriate - suppress the error, and hope.

Trigger the alarm. Or with the night vision system for the plane have some night vision goggles in the cockpit and a radar altitude warning system.

Your program is bugged. Whose to say that the alarm triggering code will function as designed under such circumstances?

Never heard of watchdogs? These are often HW devices that trigger when the SW has crashed and stops keeping them happy. Also I *have* written SW that triggers on a crash, and if you program defensively you can trigger it before the problem is bad enough to actually crash the SW!

That is not hard to debug. Stick a breakpoint on the return and you catch it immediately. Or, as I suggested above, put in logging and look at the logs. Or if it is an interactive program add in the code to report the problem to the user.

Whilst you can catch a lot of bugs at stage 1, when you are running the code through the debugger, eventually you've got to release the code without. Often to some internal QA person.

So how are you going to debug the released code which does *not* have defensive code? Why is the lack of defensive code making it easier to debug, which was you claim that I was addressing here? Also the logging would still be available in the released code as will the reports to the user. Or are you saying that you cannot understand a bug report from a user which says, "The SW reported that it cannot save an image with a negative size!"

As for writing to a log file, that's fine if you have only one program with an error-logging system set up.

It's fine with lots of them as well.

It make the code dependent on the logging system. None of the code on my website could be used if I employed such a system, for instance.

No it doesn't, and I provided part of a sample interface for you which keeps them nice and separate and allows you to use the code *without* the logging system if that is your choice.

Ah, so the contracts my company has for lots of money are to provide software built on inherently unreusable libraries. Unreusable libraries that are used in different software written and maintained by other companies.

Yes, if you are effectively writing one program / library then it solves a lot of software engineering problems. The interfaces don't need to be as clean, you can write errors to special log files, etc.

Try reading what I wrote. The library is NOT used for just one program. It is used for a number of programs written by independent companies.

You want to terminate on bugs.

Not always.

Another possible safety related (or even critical) system. The night vision system for an aircraft. There is a bug in the image processing software. Do you want the imaging to stop and not be able to see where you are going or do you want a slightly corrupted image?

We've been through this. Where human back-up isn't available, defensive programming is the best that you can do. Generally you don't want it. No results are usually better than wrong results.

You still don't get it. Defensive programming can prevent you from getting wrong results. Depending on requirements it can do this by preventing you from getting any result other than a bug report, or sometimes it can deal with the problem in such a way that the program can still produce the correct results (or some of the correct results and flag where results are not available due to the problem). In no instance is defensive programming actually *required* to hide that there is a problem.

Even a segfault is often preferable to wrong results.

Sometimes it is, sometimes it isn't. If aborting the program on a particular type of detected problem is the best thing to do then aborting it *with* an appropriate message is the action you take.

Not always, because then you can clutter the program with error messages,

Or you can do the job properly so the program is still not cluttered.

increasing maintenance costs, decreasing readability, and increasing the bug count.

I've seen one instance where incorrect defensive code increased the bug count. The defensive code also produced a report that told us what was wrong and allowed us to fix the problem in very short order. I've seen lots of instances where lack of defensive code made it very hard to find the bug.

Generally, let the system seg fault, and don't try to sanity check length parameters and the like.

So tell me, which of these bug reports will make it easier to debug...

1) The program crashed with a seg fault.
2) The program gave a screwy message saying it could not save a negative sized image!
3) The program crashed saying it could not allocate 32GB of memory, the picture was only 3x3 pixels!!!
4) The program crashed saying the foo stack was corrupted!

My experience of all these types of things is that 1 is by far the hardest to debug where as the defensive code generating the others makes it easier since you know exactly where the crash occurred and if you can't see the problem by reading the code you can stick a breakpoint on the trap with a debug version of the code, or add in more logging around the calls to the function, or anything else that suits since you have a starting point.

Oh, and for a daemon I have worked on one of the defensive actions is tracking a segfault and trying to send an email if one occurs to allow the administrator to deal with it before the users know there is a problem.

Which is an advantage of letting the system handle it.

No, it was the advantage of me adding defensive code to trap yet another error condition and handle it.

In the bad old days illegal memory writes would cause funny things to happen to the program.

Personal experience. The bad old days include today.

Now they usually cause an error mesage and program termination.

Rely on that if you want, but defensive code handles the situation even earlier, closer to the point of error and in a more controlled manner which can, if appropriate, include aborting the program with a more useful message than a SIGSEGV. Also it can save the possibly corrupted file to a different name for later attempted recovery if that is appropriate.
--
Flash Gordon
If spamming me sent it to smap@xxxxxxxxxxxxxxxxx
If emailing me use my reply-to address
See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
.