❌ About FreshRSS

Reading view

There are new articles available, click to refresh the page.

Ada is defensive by default

The type system of Ada is not merely strongly typed, but sometimes referred to as being super-strongly typed, because it does not allow for any level of implicit conversions. None. Consider the following code in C:

#include <stdio.h>
int main(void) {
   float e;
   int a;
   e = 4.7631;
   a = e;
   printf("%d\n", a);
   return 0;
}

This is valid code that will compile, run and produce the expected result – the result printed out is 4. C has no issues performing an implicit conversion. Ada on the other hand won’t even compile similar code. Here is the Ada equivalent:

with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure testtyped is
    a : integer;
    e : float;
begin
   e := 4.7631;
   a := e;
   put(a);
end testtyped;

When an attempt is made to compile this, the following error will occur:

testtyped.adb:8:09: expected type "Standard.Integer"
testtyped.adb:8:09: found type "Standard.Float"

The problem here is that a and e are clearly not the same. Instead, one has to explicitly convert between types, which promotes good design by preventing the mixing of types. In this case, Line 9 in the above code becomes:

a := integer(e);

Also at run-time, errors such as illegal memory accesses, buffer overflows, range violations, off-by-one errors, and array access are tested. These errors can then be handled safely instead of the way languages like C do. For example, consider the following C code:

#include <stdio.h>
int main(void) {
   int x[100];
   x[101] = 1;
   printf("%d\n", x[101]);
   return 0;
}

Again, this is valid code that will compile, run and produce unexpected results. A value is actually stored outside the array x. Consider the same code written in Ada:

with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure testarrOOB is
    x : array (1..100) of integer;
begin
   x(101) := 1;
   put(x(101));
end testarrOOB;

Compiling the program will result in the following warnings:

testarroob.adb:6:06: warning: value not in range of subtype of "Standard.Integer" defined at line 4
testarroob.adb:6:06: warning: "Constraint_Error" will be raised at run time
testarroob.adb:7:10: warning: value not in range of subtype of "Standard.Integer" defined at line 4
testarroob.adb:7:10: warning: "Constraint_Error" will be raised at run time

It does produce an executable, but running the executable results in an exception being triggered:

raised CONSTRAINT_ERROR : testarroob.adb:6 range check failed

Why is this important? Because in real-time systems, errors such as this have to be avoided. Now ask yourself why it is possible the F-35 code written in C++ does work as intended.

Ada is defensive by default

The type system of Ada is not merely strongly typed, but sometimes referred to as being super-strongly typed, because it does not allow for any level of implicit conversions. None. Consider the following code in C:

#include <stdio.h>
int main(void) {
   float e;
   int a;
   e = 4.7631;
   a = e;
   printf("%d\n", a);
   return 0;
}

This is valid code that will compile, run and produce the expected result – the result printed out is 4. C has no issues performing an implicit conversion. Ada on the other hand won’t even compile similar code. Here is the Ada equivalent:

with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure testtyped is
    a : integer;
    e : float;
begin
   e := 4.7631;
   a := e;
   put(a);
end testtyped;

When an attempt is made to compile this, the following error will occur:

testtyped.adb:8:09: expected type "Standard.Integer"
testtyped.adb:8:09: found type "Standard.Float"

The problem here is that a and e are clearly not the same. Instead, one has to explicitly convert between types, which promotes good design by preventing the mixing of types. In this case, Line 9 in the above code becomes:

a := integer(e);

Also at run-time, errors such as illegal memory accesses, buffer overflows, range violations, off-by-one errors, and array access are tested. These errors can then be handled safely instead of the way languages like C do. For example, consider the following C code:

#include <stdio.h>
int main(void) {
   int x[100];
   x[101] = 1;
   printf("%d\n", x[101]);
   return 0;
}

Again, this is valid code that will compile, run and produce unexpected results. A value is actually stored outside the array x. Consider the same code written in Ada:

with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure testarrOOB is
    x : array (1..100) of integer;
begin
   x(101) := 1;
   put(x(101));
end testarrOOB;

Compiling the program will result in the following warnings:

testarroob.adb:6:06: warning: value not in range of subtype of "Standard.Integer" defined at line 4
testarroob.adb:6:06: warning: "Constraint_Error" will be raised at run time
testarroob.adb:7:10: warning: value not in range of subtype of "Standard.Integer" defined at line 4
testarroob.adb:7:10: warning: "Constraint_Error" will be raised at run time

It does produce an executable, but running the executable results in an exception being triggered:

raised CONSTRAINT_ERROR : testarroob.adb:6 range check failed

Why is this important? Because in real-time systems, errors such as this have to be avoided. Now ask yourself why it is possible the F-35 code written in C++ does work as intended.

spqr

❌