| Liste des Groupes | Revenir à cl c |
On 15/06/2026 12:43, Waldek Hebisch wrote:David Brown <david.brown@hesbynett.no> wrote:On 15/06/2026 00:55, Keith Thompson wrote:<snip>David Brown <david.brown@hesbynett.no> writes:[...]>Making this UB is an admission of the blindingly obvious - there is no>
correct answer when signed integer overflow occurs. It tells
programmers that it is a mistake to let your arithmetic overflow, and
it allows tools to help programmers avoid these mistakes, and it
allows compilers to give programmers the most efficient results from
known good code rather than adding unnecessary run-time checks that
are never triggered.
Trapping or raising/throwing an exception on overflow would also be an
admission of the blindingly obvious.
It is obvious - to me, anyway - that signed overflow is a mistake in the
code. It is trying to do something that cannot be done. What is the
single-digit sum of 5 and 8? There is no answer. The answer is not 3,
or 9. Putting your hand in the air and asking the teacher for help
might be appropriate sometimes, but it is not a correct answer.
>
Throwing some kind of exception or trap can definitely be helpful at
times. And I agree that it would make it obvious that there has been a
problem detected. But throwing exceptions or traps can cause more
problems (the Ariane 5 failure was caused by the exception handler, not
the overflow fault). That does not mean it is better to ignore
overflows - it means there is no appropriate action that is suitable in
every situation. I am far from convinced that there is even a
reasonable choice of default action that could be usefully made.
>
>And a sufficiently clever compiler>
can omit some (not all) checks in cases where it can be statically
proved that overflow doesn't occur, and/or hoist some checks out of
loops.
Sure - but in practice having strict overflow checks would significantly
reduce optimisation and re-arrangement possibilities, as well as having
to include the checks themselves. You might allow non-strict checks in
some manner (thus allowing optimisations like "a + b - a" reducing to
just "b"), but I think that might be hard to specify and would reduce
the debugging help of the checks.
IMO resonable and easy definition is: computation either delivers
mathematically correct result or traps, and it is not allowed to
trap in cases where naive bottom-up evaluation does not trap.
In more formal way optimization is not allowed to introduce
stronger precondition, but may weaken it.
It is always the case that an implementation can weaken preconditions
and strengthen postconditions and remain correct - though it might then
be less efficient than you expect. But if you are /requiring/ a weaker
precondition and /requiring/ a strong postcondition - such as by
insisting on traps on overflow - you are changing the function or
operation specification, and it is not necessarily a good thing.
In C, the integer addition operation "c = a + b;" has a precondition :
(a + b) <= INT_MAX, (a + b) >= INT_MIN
It has the postcondition :
c == a + b
Saying that it must trap if there is overflow weakens the precondition
to any "a" and "b", but makes the postcondition much more complicated.
It means it is no longer true that the result of an addition operation
is the sum of the operands.
Addition is no longer a "pure" function -
now it has side-effects that are completely unpredictable at the site of
use. Programmers can no longer rely on the timing of the operation,
stack usage, interaction with other code, or even that the operation
ever finishes.
If your code is correct, and overflow never happens, then this is all a
big disadvantage in terms of understanding and analysing the code. And
it does not in any way reduce the effort needed to be sure that your
inputs are appropriate for getting the desired results of the operation.
Trapping like this can certainly be useful for debugging. But as a
general feature it gives a false sense of security, complicates
mathematical analysis, introduces massive additional possible code path
choices which are either real or almost certainly untested in practice,
or not real (because the compiler can see they are not taken) and
untestable.
That is not qualitatively worse than "who knows what will
happen" UB, but it is not significantly better.
<snip>
The correct way to handle the situation is to avoid it - be sure that
you are not dividing by zero in the first place. Identify and handle
the problem where it occurs - when this zero is created, or the
circumstances leading to that point - rather than trying to do a
post-mortem after the failed division. And if you are doing that, then
what benefit is there in having trapping for division by zero? It
becomes just a waste of effort.
What is value of certification required for some software? If
programmer did good job then program will work correctly.
Yes.
Trap give assurance that programmer indeed correctly handled
tricky problem.
No, it certainly does not. And one of the reasons to dislike traps is
that it makes people think like that. A trap can only happen if the
programmer did /not/ handle the problem correctly.
And I expect that if
the programmer is able to write an appropriate specific trap handler for
the failing expression (rather than a program-global "crash with error
message" handler), then he/she would be able to avoid the problem in the
first place.
Sometimes, of course, you are trying to write code that has some input
which is supposed to be correct, but you are not sure - and you can't
change the calling code. How you handle that situation will depend on
the program and the situation. But I don't see trapping as "correct
handling" unless the whole program is written with the expectation of
traps for error handling. You might, however, end up deciding that
trapping is the least bad option.
And once you know that computation works
according to math rules other forms of verification are easier.
You also seem to have bias to real time control: if you need
value just at given moment, then it is hard to do something
reasonable. But at least in some control areas there is
notion of "safe state", for example working heavy machine
is dangerous, stopped one usually is considerd safe. If
there is safe state, then anything not expected by program
should trigger transition to safe state.
I think if you are /not/ concerned with high efficiency in the code,
then you should be seriously questioning the choice of C as the language
in the first place. And even if you use C, there are often things you
can do to avoid having problems in the first place. The obvious one for
integer overflow is to make more use of bigger types.
In general computation, if you need correct value and have some
time there are options which may involve re-doing computation at
higher precistion, which may get rid of occasional overflows
and divisions by zero due to overflow. Division by zero may
be due to bad input data, traps allow indentification of
such data (doing it in other way may be computationaly quite
expensive).
Les messages affichés proviennent d'usenet.