www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Spec#, nullables and more

reply Gary Whatmore <no spam.sp> writes:
FeepingCreature Wrote:

 Walter Bright Wrote:
 All that does is reinvent the null pointer seg fault. The hardware does this
for 
 you for free.

Walter, I know you're a Windows programmer but this cannot be the first time somebody has told you this - YOU CANNOT RECOVER FROM SEG FAULTS UNDER LINUX. Access violations are not a cross-platform substitute for exceptions.

You're missing the point. The reason for seg faults is to terminate the application as quickly as possible. The developer then fires up the debugger and fixes the app. Seg faults should never happen in production code. You only release when all seg faults are fixed. The builtin unit tests in D can guarantee this with 100% test coverage.
Nov 06 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Gary Whatmore:

 You're missing the point. The reason for seg faults is to terminate the
application as quickly as possible. The developer then fires up the debugger
and fixes the app. Seg faults should never happen in production code. You only
release when all seg faults are fixed. The builtin unit tests in D can
guarantee this with 100% test coverage.

Unittests help remove and avoid some bugs, but experience shows they don't solve/avoid all problems. Null exceptions do happen in production code. 100% coverage of unittests can't avoid all possible bugs, because it's easy to miss some code paths in unittests. Take a look at bugzilla to see many basic bugs in Phobos despite the usage of unittests. Bye, bearophile
Nov 06 2010
parent reply Walter Bright <newshound2 digitalmars.com> writes:
bearophile wrote:
 Gary Whatmore:
 
 You're missing the point. The reason for seg faults is to terminate the
 application as quickly as possible. The developer then fires up the
 debugger and fixes the app. Seg faults should never happen in production
 code. You only release when all seg faults are fixed. The builtin unit
 tests in D can guarantee this with 100% test coverage.

Unittests help remove and avoid some bugs, but experience shows they don't solve/avoid all problems. Null exceptions do happen in production code. 100% coverage of unittests can't avoid all possible bugs, because it's easy to miss some code paths in unittests. Take a look at bugzilla to see many basic bugs in Phobos despite the usage of unittests.

Do a: make -cov in the phobos directory, which will run the coverage analyzer on all the unit tests in the library. You'll find that the coverage is nowhere near 100%. Granted, even 100% coverage is no guarantee of no seg faults, but in practice it is very effective. And finally, null exceptions are not a bug. They are the messenger that there is a bug in the code. Until one knows why a null pointer was dereferenced, one cannot conclude that the existence of the null pointer was the bug.
Nov 06 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Walter:

 Granted, even 100% coverage is no guarantee of no seg faults, but in practice
it 
 is very effective.

Unittests are widely used in Java, still null exceptions are not uncommon in Java.
 And finally, null exceptions are not a bug. They are the messenger that there
is 
 a bug in the code. Until one knows why a null pointer was dereferenced, one 
 cannot conclude that the existence of the null pointer was the bug.

I see, null exceptions are not a bug. But for the semantics of a part of a program it may be a bug to put a null inside a collection or inside a variable, or it may be a bug to pass a null to a certain function. Those are true bugs. A notnull type allows you to spot the bug, because the type system screams (if you have asked those things to be nonnull) Your may write your function like this: void foo(T x) {...} it means T can't be null. As you say a segfault inside foo() is not a bug, the real bug is where that x was initialized, collected or created. The advantage of a nonnull type is that you will receive an error when you try to put a null inside the variable that will later be passed to foo(), this means where the true bug is. That foo() is also better than this: void foo(T x) in { assert(x !is null); } body {...} Because: - You need to put a whole precondition there, while in the other case you just need to add a . Less typing, etc. - The test is done (or not done) at run-time. This slows down the function a little. In release mode you don't have the slowdown, but you lose the safety. - The D contract system is not enforced at compile-time. This means that the true spot where the bug is, where the variable that later will become x is created, is not spotted. So your program will keep working until you call foo() and then a runtime exception or segfault will be generated. Instead if you are using a static type system, it means you are using that suffix, the type system statically spots the possible problem for you (it somehow forces you to put a nonnull inside the variable that will become x. At worst this will require a runtime test. But this test is done only once, if you later you call another function bar() with he same nonnull argument, it too will not need another runtime test). Bye, bearophile
Nov 06 2010