On 03/06/2012 03:39 PM, Mantis wrote:
06.03.2012 8:04, Chad J пишет:
On 03/06/2012 12:07 AM, Jonathan M Davis wrote:
If you dereference a null pointer, there is a serious bug in your
program.
Continuing is unwise. And if it actually goes so far as to be a segfault
(since the hardware caught it rather than the program), it is beyond
a doubt
unsafe to continue. On rare occasion, it might make sense to try and
recover
from dereferencing a null pointer, but it's like catching an
AssertError. It's
rarely a good idea. Continuing would mean trying to recover from a
logic error
in your program. Your program obviously already assumed that the
variable
wasn't null, or it would have checked for null. So from the point of
view of
your program's logic, you are by definition in an undefined state, and
continuing will have unexpected and potentially deadly behavior.
- Jonathan M Davis
This could be said for a lot of things: array-out-of-bounds
exceptions, file-not-found exceptions, conversion exception, etc. If
the programmer thought about it, they would have checked the array
length, checked for file existence before opening it, been more
careful about converting things, etc.
It's different: with array-out-of-bounds there's no hardware detection,
so its either checked in software or unchecked (in best case you'll have
access violation or segfault, but otherwise going past the bounds of
array leads to undefined behavior). Both file-not-found and conv
exceptions often rely on user's input, in which case they do not
necessarily mean bug in a program.
Alright.
To me, the useful difference between fatal and non-fatal things is how
well isolated the failure is. Out of memory errors and writes into
unexpected parts of memory are very bad things and can corrupt
completely unrelated sections of code. The other things I've
mentioned, null-dereference included, cannot do this.
Null-dereferences and such can be isolated to sections of code. A
section of code might become compromised by the dereference, but the
code outside of that section is still fine and can continue working.
Example:
[...]
And if riskyShenanigans were to modify global state... well, it's no
longer so well isolated anymore. This is just a disadvantage of global
state, and it will be true with many other possible exceptions too.
Long story short: I don't see how an unexpected behavior in one part
of a program will necessarily create unexpected behavior in all parts
of the program, especially when good encapsulation is practiced.
Thoughts?
If riskyShenanigans nullifies reference in a process, then it must check
it before dereferencing. There's obviously a bug, and if program will
leave a proper crash log you shouldn't have problems finding and fixing
this bug. If you don't have access to function's source, then you cannot
guarantee it's safeness and isolation, so recovering from exception is
unsafe.
But what do you say to the notion of isolation? someFunc is isolated
from riskyShenanigans becuase it /knows/ what state is touched by
riskyShenanigans. If riskyShenanigans does something strange and
unexpected, and yes, it does have a bug in it, then I feel that someFunc
should be able to reset the state touched by riskyShenanigans and
continue.
The thing I find really strange here is that there's this belief that if
feature A is buggy then the unrelated feature B shouldn't work either.
Why? Shouldn't the user be able to continue using feature B?
Btw, crashing a program is bad. That can lose data that the user has
entered but not yet stored. I should have a very good reason before I
let this happen.
It would also be extremely frustrating for a user to have a program
become crippled because some feature they don't even use will
occasionally dereference null and crash the thing. Then they have to
wait for me to fix it, and I'm busy, so it could be awhile.
My impression so far is that this hinges on some kind of "where there's
one, there's more" argument. I am unconvinced because programs tend to
have bugs anyways. riskyShenanigans doing a null-dereference once
doesn't mean it's any more likely to produce corrupt results the rest of
the time: it can produce corrupt results anyways, because it is a
computer program written by a fallible human being. Anyone trying to be
really careful should validate the results in someFunc.