C/C++ style Crashes?

Sebastian Biallas groups.5.sepp at spamgourmet.com
Fri Jan 12 12:10:49 PST 2007


Alexander Panek schrieb:
> Sebastian Biallas wrote:
>>>> [...]
>>>> It just doen't solve the problem that you have a bug in your program in
>>>> the first place. Reread that sentence.
>>> Exceptions can be handled at runtime, still. try (to) catch it and there
>>> you go. :)
>>
>> So, how exactly do you /handle/ an exception which "should not be there"?
> 
> One has to make sure to catch all "should not be there" exceptions, too 
> (ideally). In the real world, of course, there can happen to be mistakes 
> in the code, hidden bugs and what not else. But the fact is, that in 
> most software, that is really fully tested, those happen very rarely and 
> can be handled with special routines - 

By what routines?

> maybe also automatically sending 
> a bug report to the developers or the IT department of a company. 

You can do this with C code, too (see talkback from mozilla)

> This 
> depends on what kind of software you write/use(libraries). Apart from 
> that, D has this neat scope(fail) thing, that will cover almost all 
> circumstances, except segmentation faults .. ;)

scope(xx) is nice, that's right.

>>>> Getting an unexpected exception in a shipped application is a huge bug.
>>> That's why you always /test/ everything so good, that you just don't get
>>> unexpected exceptions.
>>
>> Well, so you shouldn't need exceptions at all for array handling, right?
>> (Except for debugging, where they really help)
> 
> As soon as the amount of /dynamic/ data you have to handle grows, I 
> don't think there's a way around using at least exceptions to stay safe.

I'm not sure I understand that sentence.

Maybe I should clearify my point:
Exceptions are a nice way to handle unpredictable situations at runtime, 
like an IO error. Java helps you even with this, when you use the 
throw() specifier for your io-functions.

But exceptions are IMHO a wrong way to handle /programming mistakes/. 
Programming mistakes must be fixed by a programmer -- they can't be 
fixed at runtime. It's just too late if a buggy program is running.

>> So what to do now? The program is now in an unstable state.
>> And even if you catch the Exception on the right place: The Exception
>> should never have been thrown. There is a bug, and the bug is not
>> necessarily at the place where the exception was thrown -- the program
>> might have been in an inconsistent state for hours.
> 
> This is, of course, not so good. But then again, you should design the 
> software in a way that avoids such circumstances (yes, this is not 
> possible in any cases, but in very much).

This is pretty much the answer you get from someone advocating C or C++ 
if you ask him why a C or C++ program behaves in such an unpredictable 
way ;)

>>> They worked for me
>>> pretty well so far to avoid a unhandled exceptions that just terminate
>>> the program.
>>
>> It would be even better if the compiler could prove at compiler-time,
>> that there are no OutOfBound, NullPointer and CastExceptions possible.
> 
> AFAIK, D handles this as long as it's not dynamic data. As soon as array 
> indexes, pointer arithmetic or other not so exotic things kick in, 
> there's no way to determine what values/states there can be. 

You need a careful designed language for this. See e.g. SPARK (I haven't 
used it yet).

>>
>> While this is hard for ArrayOutOfBounds, there are quite easy ways for
>> avoiding NullPointer and CastExceptions at all. In the language Nice[1]
>> they do this as follows:
>>
>> NullPointer: They have different types for pointers that can be null
>> (?Type) and pointer that can't (Type). You can't dereference a ?Type
>> variable.
>>
>> So, let's say we have
>>
>> void foo(?Type t)
>> {
>>     // we want to dereference t
>>     if (t != null) {
>>         // now the compiler "magically" converts t to type Type
>>         t.doSomething();
>>     }
>> }
> 
> How about:
> 
> void foo ( Type t )
> in {
>     assert( t != null );
> }
> body {
>     t.doSomething();
> }
> 
> I find this rather equal.

It is rather equal. The difference is not in the source code, the 
difference is how you /can/ write this.

In Nice you just have this one possibility: If you want to dereference a 
?pointer, you have to test it against null -- otherwise it won't 
compile. In other languages this test is optional (and even whether a 
pointer can be null is not part of the language but of the 
documentation. And documentation is often not available or wrong).

Of course you can write correct code in D and other languages. The point 
is: In Nice the code is guaranteed to be correct regarding null-pointer 
checks once it compiles! There is no need of a "style guide" for this 
which will be ignored once the project reaches its deadline.

>> TypeCasts: You don't cast with a cast-operator, but with a
>> instance-of-expression:
>>
>> void bar(A a)
>> {
>>     if (a instanceOf B) {
>>         // now a is of type B, no need to cast
>>     }
>> }
> 
> What exactly does an instance-of-expression? Never seen this, actually.

	if (a instanceOf B) {

is the same as

	if (dynamic_cast<B>(a)) {  // in C++

or

	if (cast(B) a) { // in D



More information about the Digitalmars-d mailing list