newbie conceptual question [from haskell list]
Fri, 27 Jul 2001 14:04:42 +0100 (BST)
Important confession since Fergus is in the discussion: I've not actually
read any of the C or C++ standards; I've got an impression of what they
say from various textbooks and the gcc mailing lists.
On Fri, 27 Jul 2001, Fergus Henderson wrote:
> But there are so *many* such "stupidities".
> If you took out all of the things in C that had
> implementation-defined, unspecified, or undefined behaviour,
> then what you'd be left with wouldn't be C.
> If you were talking about some other C-like language, such as
> LP-C, Java, or C#, then I think your point might be valid.
> But the differences between C and higher-level imperative (or OOP)
> languages should not be ignored.
I'm sure you're right. However, this seems to fit paradoxically with my
personal experience, and that of the people that I discuss this stuff with
at work. This may be something to do with the fact that we're developing
programs of the scientific kind (e.g., image segmentation) and that
virtually everyone tends to unconsciously follow the KISS (Keep it simple,
stupid) principle: our goal is very much to produce programs that `do cool
things' rather than `are cool due to the way they are coded'. And I
_still_ don't think that there are that many bugs that hit me due to
implementation definedness or weird corner-cases in the syntax. If you had
a time machine, took a piece of code that I'll write in the future with a
bug in it and asked me to figure out what the bug in there was I bet that,
in most cases given just enough time, patience, paper and coffee I could
find the bug without a computer and it wouldn't be involve the compiler
defining something one way whereas I thought the standard defined it
another. I generally don't produce programs with bugs because the compiler
implements some particular construct differently to the way that I think
it sould but because I can't keep the whole program and the interactions
between all its parts straight in my very limited mind.
(I feel like a bee-keeper at apocryphal dinner party where it's said
that by the laws of physics bees can't fly: all the other parties in this
discussion are much more technically competent and well-read than me and
yet my actual experiences don't seem to accord with their conclusions
> > Likewise, C and
> > C++ have specifications which are met to a reasonable degree by many
> > compilers out there, which prompts the question: when was the last time a
> > bug in your code in an imperative language was due to an
> > implmentation-defined part of the language? In 5 years of intensive C++
> > programming I'd guess I've made maybe 25 bugs due to this, but the number
> > of bugs I've fixed in my code must be in the tens of thousands.
> If you also include areas which are unspecified or undefined, as well
> as those that are implementation-defined, I think it would cover a
> very substantial proportion of those tens of thousands of bugs.
> How many times have you written code that accidentally referenced
> an uninitialized variable, for example? Or that accessed memory
> after it had already been deallocated? Or that tried to access
> past array bounds? These are very common kinds of errors.
I haven't been very precise in my terminology (and as I say haven't
actually read the standards). When I talk about something being
implementation defined I mean that the precise details of how it is
defined in an implementation needs to be understood for a `bug-free'
program to work. I've been calling a statement (which I'm not claiming to
have read verbatim anywhere) like `accessing memory outside allocated
array bounds can non-determinisitically corrupt any part of the overall
state of the program, return correct or gibberish results or cause the
program to abort' to be perfectly reasonable defined statement of what to
expect. It can certainly be viewed as either `under'-defined, or that what
actually happens to be implementation defined. But I don't consider that
when I screw up by allocating memory outside array bounds to be a bug due
to implementation-definedness, it's a bug because I didn't spot some
interaction that caused the variable that I was accessing the array at to
become a value that was to big.
But to some extent I've been arguing about C just because I think I'm
right rather than because I think it's important to considering the
overall question. Suppose that I'm working in Java. I'm told that if an
access is made to a index outside the range of an array it throws an
exception. How would you classify the following situation:
* within some routine f:
* a variable v is set up which holds the (valid) index at which I want to
access the array at the start of the routine.
* somewhere deep in a lot of code something ERRONEOUSLY assigns a value to
that variable v which is outside the range of the array.
* a read of the array at index v is attempted. An exception is thrown.
* an catch block governing f catches the exception and prints out `Attempt
to access array outside its range.'
Nothing here is talking about unspecified semantics, or implementation
definedness. Has the actual problem which is causing my program to not be
useable for its intended purpose (`the bug') gone away? Is the bug
fundamentally different to what it would be in a C implementation? If you
were asked what the cause of the bug was, would you say that it was
anything other than the erroneous assignment to v?
Basically my argument was that in an imperative language the semantics do
not generally cause the problem of figuring out why v has the wrong value
(or equivalently, being sure when I wrote the code that v has the correct
value) to fall apart into sufficiently small problems that effective
reasoning becomes possible. On the other hand I believe the semantics of
functional languages _do_ have this `meta-property'.
www.cs.bris.ac.uk/~tweed/pi.htm |tweed's law: however many computers
email: firstname.lastname@example.org | you have, half your time is spent
work tel: (0117) 954-5250 | waiting for compilations to finish.