Re: Undefined behaviour [was Re: The D Programming Language]
David Abrahams wrote:
"Andrei Alexandrescu (See Website For Email)"
<SeeWebsiteForEmail@erdani.org> writes:
David Abrahams wrote:
"James Kanze" <james.kanze@gmail.com> writes:
Ian McCulloch wrote:
Right - and there are systems that already do this. Valgrind (
http://www.valgrind.org/) springs to mind at this point. In the face of a
programming error, you want as much `undefined' behaviour as possible, to
give the tools that detect such behaviour the most information possible.
Except that you only need such tools because of the undefined
behavior.
Completely backwards. You can only _use_ such tools because of the
undefined behavior. You still need something to detect the incorrect
logic that in C++ would have caused UB and in Java causes
who-knows-what "defined" behavior. But no such tool exists, or can
exist.
I'm not sure I figure the logic. Java statically disallows a number
of programs that in C++ are allowed and would be correct. It also
disallows statically a number of programs that in C++ are allowed,
and that are not correct.
And there are plenty of programs with incorrect logic that is allowed
by both languages. In C++ that incorrect logic may lead to undefined
behavior, which is detectable by tools at runtime. In Java it cannot.
Or can. It depends on the error. And the tools. There's a lot
of incorrect logic which cannot be caught by any tool. There
are also programs which will be correct in Java (because it
defines behavior that C++ doesn't) but incorrect in C++. And
some of these C++ errors will not necessarily be caught be a
tool---it's not undefined behavior, but consider the case of "f(
auto_ptr( new X ), auto_ptr( new Y ) )". The code is an error
in C++---both you and I know this. But Purify won't catch it
unless 1) you actually do get an exception in one of the
expressions, and 2) the compiler actually has interleaved the
code in a specific way. You and I actually ensure that the test
cases include 1), but I'm not sure that the practice is
universal. And I don't know of any way to ensure that all
possible orders of execution are generated by the compiler.
The problem, and Andrei has pointed it out as well, is that in
some cases, the behavior really is undefined. Dereferencing an
uninitialized pointer, for example. Statistically, there's a
good chance that valgrind or Purify will catch it, but it is NOT
guaranteed. In Java, the contents of the pointer are guaranteed
to be either null (and you can test for it), or memory that it
points to is not being used for something unrelated. A pointer
will never contain just random bits, which might point anywhere.
And while this situation isn't perfect either, it does mean that
your code is considerably more predictable and deterministic.
Which in turn means that if you test thoroughly, there is a
significantly less chance of an error accidentally slipping
through your tests---the code that you deliver behaves largely
the same as it did when you tested it.
And again, it's a question of degree. I reject all claims to
perfection, at least as long as the language is designed by
human beings. I disagree with Andrei that it is possible to
create a language with no undefined behavior. But that doesn't
mean that I don't appreciate the advances that have been made in
that direction. Knowing just where all pointers point won't
guarantee that my program will work. But it does make it easier
for me to add verification code that I know will work, and it
makes the execution more deterministic, and more reproduceable,
and thus increases the signifiance of my tests.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]