Safe version of gets

M

Malcolm

Richard Heathfield said:
Martin's advice was fine. Your example is flawed. Firstly, it is the
doctor,
not the computer program, that is responsible for the patient's safety.
Secondly, NONE of the behaviours you demonstrate is preferable. The
program
should accept the input completely, and process it completely, and produce
the completely correct output. This is hardly difficult.
A correct program is preferable to an incorrect one. That's the first
principle of software engineering.
fgets() can be used correctly, unfortunately it is too difficult for the
average programmer to do so. The human factor is something that people often
overlook. We have Martin Ambuls as well as Richard Heathfields as
professional C programmers. You personally will never forget to check for
that trailing newline that indicates an entire line has been read. Lesser
programmers are not always as diligent.

As for your first point, of course I chose an example where the consequence
of an error was death, in order to make the point. In reality Blogg's
restaurant supplies would get 1000 pizza bases instead of 800, with the
consequence that someone has got to get into a van and collect them. 50
pounds cost to the company. Not the end of the world, but not something you
want your software to be responsible for either.
 
M

Malcolm

Flash Gordon said:
That's swapping bugs, and if the new bug is more likely to produce
reproducible symptoms, then you have at least reduced the average time to
debug the program.
That's the argument. It does have a certain force. However my experience is
that, in practise, it is erroneous.

let's say we ahve the following

void setname(EMPLOYEE *emp, char *name)
{
strcpy(emp->name, name);
}
Now if fact the name member isn't long enough to hold the string passed.
Muggins does the following

void setname(EMPLOYEE *emp, char *name)
{
if(strlen(name) < (sizeof emp->name) - 1)
strcpy(emp->name, name);
}

That's suppressing the error. He gets rid of the UB, but the poor caller has
now got to work out why his call to setname is having no effect.

What Muggins should do is of course work out why setname is being passed an
over-long name, and root out the error. He might also consider whether
setname() should assert fail on being passed an over-long string, or even
exit.

What Muggins has done will almost certainly, in practise, make the program
much more difficult to debug.
 
R

Richard Heathfield

Malcolm said:
You personally will never forget to check for
that trailing newline that indicates an entire line has been read.

Nonsense. Of course I will forget, sometimes. That's why program validation
methods - code reviews, unit tests, etc - are so important.
In reality
Blogg's restaurant supplies would get 1000 pizza bases instead of 800,

Only if your idea of testing is "look! it compiles!"
 
R

Richard Heathfield

Malcolm said:
That's the argument. It does have a certain force. However my experience
is that, in practise, it is erroneous.

let's say we ahve the following

void setname(EMPLOYEE *emp, char *name)
{
strcpy(emp->name, name);
}
Now if fact the name member isn't long enough to hold the string passed.
Muggins does the following

void setname(EMPLOYEE *emp, char *name)
{
if(strlen(name) < (sizeof emp->name) - 1)
strcpy(emp->name, name);
}

That's suppressing the error. He gets rid of the UB, but the poor caller
has now got to work out why his call to setname is having no effect.

That's because he used data validation techniques to validate the program.
Assuming emp->name is an array (because, if it isn't, the technique needs
to be modified very slightly), what he should have done is something like:

What Muggins has done will almost certainly, in practise, make the program
much more difficult to debug.

Moral: don't employ mugginses to cut production code.
 
R

Richard Heathfield

Malcolm said:
An awful lot of errors are introduced into programs in just that way. A
bug is discovered, and someone puts in a quick fix to suppress the
symptoms, without really getting the root of the problem.

Ah, I see. Yes. That's a very good point. Hmmm. Introducing bugs as a
problem-solving technique. I hadn't thought of that. I must try it.

That might explain why there are so many bugs in today's software! They are
not problems, but solutions! We should embrace and welcome them!

(FCOL)
 
F

Flash Gordon

Malcolm said:
That's the argument. It does have a certain force. However my experience is
that, in practise, it is erroneous.

My *personal* experience is that it is true. I have had to debug many
instances of UB introduced by others, and with the exception of
dereferencing NULL pointers (which happens to cause an immediate crash)
UB is harder to debug than incorrect but defined behaviour because it is
predictable and because corrupting memory often leads to a crash later
in the code rather than visibly incorrect behaviour at the place where
the bug is.
let's say we ahve the following

void setname(EMPLOYEE *emp, char *name)
{
strcpy(emp->name, name);
}
Now if fact the name member isn't long enough to hold the string passed.
Muggins does the following

void setname(EMPLOYEE *emp, char *name)
{
if(strlen(name) < (sizeof emp->name) - 1)
strcpy(emp->name, name);
}

That's suppressing the error. He gets rid of the UB, but the poor caller has
now got to work out why his call to setname is having no effect.

What Muggins should do is of course work out why setname is being passed an
over-long name, and root out the error. He might also consider whether
setname() should assert fail on being passed an over-long string, or even
exit.

What Muggins has done will almost certainly, in practise, make the program
much more difficult to debug.

No, the second example with defined behaviour is vastly easier to debug.
With the first example the software may well visibly crashes millions of
instructions later in a completely different part of the code. With the
second example you know that the name is not being set so you step
through (or read) the code setting it and immediately find the problem.
So an excellent eexample of code where incorrect but defined behaviour
is far EASIER to debug than undefined behaviour.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top