Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!ncar!tank!shamash!com50!midgard!syntel!dal From: dal@syntel.UUCP (Dale Schumacher) Newsgroups: comp.os.minix Subject: Re: Future of Minix (error checking) Message-ID: <062489A1942@syntel.UUCP> Date: 24 Jul 89 15:43:22 GMT Reply-To: dal@syntel.UUCP (Dale Schumacher) Lines: 70 X-Member-Of: STdNET (ST Developer's Network) [ast@cs.vu.nl (Andy Tanenbaum) writes...] > In article <061989A1660@syntel.UUCP> dal@syntel.UUCP (Dale Schumacher) writes: >>I want all that error checking OUT OF THE WAY when I go to create my >>final program. > > It is sort of like going to sailing school and wearing a life preserver > during the theory part on land, but refusing to wear it when you get in > the boat. I don't think the analogy is valid, partially because the life preserver don't make the boat go half as fast (or worse). The C standard library has a long tradition of minimal error checking. This gives nice efficient code, but can make debugging a real hassle. The way I look at it, there are two ways that a library function can be given parameters which will cause an error. The first is through a data-dependent bug. A certain input stream creates an error condition, like the user entering "0" when asked "Enter number of people to divide the profits by:". It is difficult to catch this kind of error during testing, since the error condition may never occur in the test input. The second kind of problem is a bad call in the program, often due to faulty program logic or mismatched parameters. This kind of error is easier to discover, since it will likely cause the program to function improperly, but the symptoms may not be clearly indicative of the actual problem, since the libarary function behaviour is "undefined" for such a condition. The solution to the first problem involves good run-time checking of all input data to assure that it is within acceptable ranges. THIS KIND OF RUN-TIME CHECKING SHOULD STAY IN THE PROGRAM. Debugging the second kind of problem can be helped by heavy run-time argument checking in all of the library functions, but once the program is reasonably stable, THIS KIND OF CHECKING CAN BE REMOVED, since we now assume that will will not call a library function with bad parameters. Of course there will likely be areas we haven't tested well enough, but if the program starts behaving strangely under some circumstances, we can re-link it with the error checking library and may catch the bug that way. > I think the right way to do it is with the ASSERT() macro. There is a large > theoretical literature about program correctness using assertions, so this > way is clearly not a hack. If done right, it also has documentation value. > And it generates no life preserver anywhere near the water. ASSERT() is very useful, and I fully agree that it should be used far more that is usually is. However, it doesn't do the whole job. It serves the function of gaurding against error condition, where they can be checked ahead of time, but there are other times where something which gives a little more information (like parameter values) or just prints a warning (rather than aborting the program) would be more helpful. In these cases, I think the following is more flexible. #ifdef NDEBUG #define DEBUG(x) /* x */ #else #define DEBUG(x) x #endif There is a place for both ASSERT() and DEBUG() in an error-checking library. > Andy Tanenbaum (ast@cs.vu.nl) PS. The inverted logic of NDEBUG means that by default debugging or assertion code is included, which seems to be a GOOD THING (tm). If you want faster (and less safe) code you must explicitly ask for it. \\ / Dale Schumacher 399 Beacon Ave. \\ / (alias: Dalnefre') St. Paul, MN 55104-3527 >< ...umn-cs!midgard.mn.org!syntel!dal United States of America / \\ "What is wanted is not the will to believe, but the will to find out, / \\ which is the exact opposite." -Bertrand Russell