Re: Class hierarchy of exceptions (Ada, C++)
From: Tapio Kelloniemi (spam17_at_thack.org)
Date: Wed, 30 Mar 2005 11:35:14 GMT
"Peter Koch Larsen" <email@example.com> wrote:
>"Tapio Kelloniemi" <firstname.lastname@example.org> skrev i en meddelelse
>> The question is not only about compiler warnings or errors. Ada (as a
>> language) has been designed so that it is possible for the
>> compiler to check many mistakes which may cause bad results at run time.
>> Ada also makes it easier for the user to notice this kind of errors.
>> For example:
>> procedure X is
>> type Metres is new Natural;
>> type Seconds is new Natural;
>> M : Metrses := 0;
>> S : Seconds := 10;
>> if M < S then -- Error, < is not defined for these types
>But now you have problems calculating the velocity, right?
>type Velocity is new Natural;
>V: Velocity = M/S; // probably a compiler error.
Yes, but I can tell the compiler that I know better:
V : Velocity := Velocity (Integer (M) / Integer (S));
Also other readers of my code now know surely that this is what I meant.
>> This is a bit more verbose than using pure int instead of Metres and
>> Seconds, but if I wanted a C++ compiler to check this kind of error, I'm
>> afread that the resulting C++ code would be much more verbose.
>Not so. There is an excellent library which does exactly what you want -
>using templates, of course.
That is a good thing. If all C++ programmers used it, I think their
programs would benefit a lot of it.
>> Such mistakes as using a pointer to nothing and writing past the array
>> bounds don't often happen in Ada.
>What makes you believe they happen regularly in C++?
They just happen. Why people had otherwise created such tools as valgrind
(http://valgrind.kde.org/). I also use it myself for Ada to eliminate memory
leaks. Writing past array bounds unintentionally is quite easy. In Ada
Constraint_Error is raised, but C++ program segfaults. Or even worse, it
does not segfault immediately, but when the function is exited (as the
return address has been destroyed). STL is safer, but it cannot always be
used (eg. when interfacing to foreign code).
>>>An example. First compile with the default behaviour, then with all
>> If a replace I < J; with null; the result is:
>> gcc -c -gnatg temp.adb
>> temp.adb:2:04: warning: "I" is not modified, could be declared constant
>> temp.adb:2:04: warning: variable "I" is not referenced
>> temp.adb:3:04: warning: "J" is not modified, could be declared constant
>> temp.adb:3:04: warning: variable "J" is not referenced
>> gnatmake: "temp.adb" compilation error
>I see no real difference here between a good-quality C++ compiler and Ada.
int i = 3;
int& l = *(new int);
l = i;
int* p = &i; // Should be int* p = &l;
int* p = f();
*p = 4;
# g++ -Wall -o temp temp.cc
Not even a warning and the program does not crash on my system! Valgrind
revealed the error (and thought it was a G++ bug).
If the code above is modified a bit, even the best compiler cannot
know for sure that we are doing evil things.
The same in Ada:
procedure Temp is
type Int_Ptr is access Integer;
function F return Int_Ptr is
I : Integer := 3;
L : Int_Ptr := new Integer;
P : Int_Ptr;
L.all := I;
P := I'Access; -- Should be P := L;
A : Int_Ptr;
A := F;
A.all := 4;
# gcc -c -gnatg temp.adb
temp.adb:5:04: (style): subprogram body has no previous spec
temp.adb:11:12: prefix of "Access" attribute must be aliased
So if I really want to pass a pointer to a local to the caller, I should
I : Integer := 3;
I : aliased Integer := 3;
Also note that the lines which were "mistyped" are much closer to each
other in C++ than in Ada.