C Traps and Pitfalls. • by Andrew ... B fitenes. • http://libre.act-europe.fr/Why_Ada/
ada-on-jvm.pdf .... This lecture is not an exhaustive list of C/C++/Java pitfalls.
Programming in the Small: C/C++/Java Pitfalls & Ada Benefits Franco Gasperoni gasperoni@adacore com
[email protected] http://libre.adacore.com/Software_Matters
Copyright Notice © AdaCore under the GNU Free Documentation License Permission is ggranted to copy, py, distribute and/or modifyy this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; provided its original author is mentioned and the link to http://libre.act-europe.fr/ is kept. A copy of the license is included in available at: http://www.fsf.org/licenses/fdl.html
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
2
Suggested Reading C Traps and Pitfalls • by Andrew Koenig (Addison Wesley)
Guidelines for the Use of the C Language in Vehicle Based Software • Purchasing http://www.misra.org.uk/misra-c.htm P h i iinfo f att htt // i k/ i ht
Multilanguage Programming on the JVM: The Ada 95 B fit Benefits • http://libre.act-europe.fr/Why_Ada/ada-on-jvm.pdf
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
3
Other Interesting Material Other Interesting Links • http://www.elj.com/cppcv3/ - A critique of C++ C
• http://www.cs.mdx.ac.uk/harold/srf/javaspae.html - A critique of Java
• http://www.jaegers.net/humor/stroustrup.php http://www jaegers net/humor/stroustrup php - Stroustrup's interview leaked :)
• http://www.web-hits.org/txt/codingunmaintainable.html - How to write unmaintainable code
Other interesting books • Effective Eff ti C C++, by b S Scotttt M Myers (Addi (Addison W Wesley) l ) • Java Pitfalls, by Michael C. Daconta et al., (Wiley) • Objects j Unencapsulated: p Java,, Eiffel,, and C++,, byy Ian Joyner y ((Prentice
Hall)
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
4
Lecture Summary In this lecture we concentrate on programming in the small We go over some Ada basic constructs • Procedures, Proced res functions, f nctions ttypes, pes loops loops, if and case statements eexceptions, ceptions
etc.
We show some C/C++/Java pitfalls We show how Ada avoids them
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
5
What is Programming in the Small ? A computer can only perform very simple operations Ap program performs complex g p p tasks • By grouping together large numbers of simple operations
Programming in the large • Deals with the overall structure/architecture of the program
Programming in the small • Deals with the program details once the overall structure is in place
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
6
Programming: Abstraction Structure & Coding Detail Abstraction,
Uses the services of
Structuring element: package, g , Module,, p class, file, … http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
7
Programming in the Large Designing the abstractions and structure around which the simple computer operations will be organized The structuring unit varies from language to language • E.g. module, package, class, file, etc.
This is like doing the architectural drawing of a building
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
8
Programming in the Large: Abstraction & Structure
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
9
Programming in the Small Programming in the small is also known as coding This activityy refers to filling program g in the details of the p g architecture elaborated in the Programming in the Large The details are the explicit, step by step instructions for explicit step-by-step performing fairly small-scale tasks • Arithmetic operations, loops, decisions, etc.
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
10
Programming in the Small: Coding Detail … max_gnat_nodes = max_gnat_node; number names number_names = number_name; number name; Nodes_Ptr = nodes_ptr - First_Node_Id; Next_Node_Ptr = next_node_ptr - First_Node_Id; Prev Node Ptr Prev_Node_Ptr = prev_node_ptr prev node ptr - First_Node_Id; First Node Id; Elists_Ptr = elists_ptr - First_Elist_Id; Elmts_Ptr = elmts_ptr - First_Elmt_Id; Strings Ptr Strings_Ptr = strings_ptr strings ptr - First_String_Id; First String Id; String_Chars_Ptr = string_chars_ptr; List_Headers_Ptr = list_headers_ptr - First_List_Id; … if (Nkind (gnat_root) != N_Compilation_Unit) gigi_abort (301); …
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
11
Programming in the Small with C C makes the following assumption: • Trust the programmers, they never make mistakes • Favor program conciseness over its readability
But: • P Programmers do d make k mistakes i t k • Programs are written once but read many times
Th C foundation f d ti off C++ C & Java J l d to t fragile f il software ft The leads • Software where it is easy to make mistakes • Software that is hard to read • Software that is hard to change
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
12
Important Note All C/C C/C++/Java /J code d examples l showed h d iin thi this llecture t compile il • Some are correct according to the C/C++/Java semantics • Others are specified to be errors in the standards but … p • … an implementation is not required to detect them
g errors undetected byy most C/C++/Java Theyy contain coding compilers Most of the p pitfalls shown in this lecture are written in C/C++ • They can easily be converted to Java
Some p pitfalls onlyy occur in C/C++ and not in Java • When this is the case it will be pointed out in the example
Thiss lecture ectu e iss not ot an a exhaustive e aust e list st of o C/C++/Java C/C /Ja a ppitfalls ta s • There are more http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
13
N t on th Note the Ada Ad Development D l t Environment E i t In this course we use GNAT GAP Edition GNAT is widelyy available • You can download the sources of GNAT • Pre-built GNAT binaries available for: Linux, Solaris, Windows
GNAT GPL Edition available at • http://libre.adacore.com
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
14
Background on Ada Programming A Simple Example
Procedure Main Procedure Main • •
with Text_IO; procedure Main is Length : Integer := 8265; Width : Integer := 0252; H i ht : Integer Height I t := 8292 8292; begin Text_IO . Put_Line (Length'img); Text IO . Put_Line Put Line (Width'img); Text_IO Text_IO . Put_Line (Height'img); end Main;
Note: Ada is case insensitive http://libre.adacore.com
Stored in file main.adb main adb Technically this is called a compilation unit
A compilation p unit can be the bodyy or the spec (specification) of a: • • •
procedure function package (see next lecture)
Spec = precise list of services exported Body = implementation details In GNAT: • • •
1 compilation unit per file File name matches unit name 2 file extensions possible - .adb db = Ad Ada B Body d - .ads = Ada Spec
© AdaCore under the GNU Free Documentation License
16
Inside Procedure Main
with Text_IO; procedure Main is Length : Integer := 8265; Width : Integer := 0252; H i ht : Integer Height I t := 8292 8292; begin Text_IO . Put_Line (Length'img); Text IO . Put_Line Text_IO Put Line (Width'img); Text_IO . Put_Line (Height'img); end Main;
http://libre.adacore.com
Declarative part: Contains the declaration of: •
Variable, types, nested procedures, nested f ti functions, ... usedd iin procedure d M Main i
Procedure statements
© AdaCore under the GNU Free Documentation License
17
with Text_IO; Text IO; List of compilation units whose services are used in procedure Main
with Text_IO; procedure Main is Length : Integer := 8265; Width : Integer := 0252; H i ht : Integer Height I t := 8292 8292; begin Text_IO . Put_Line (Length'img); Text IO . Put_Line Put Line (Width'img); Text_IO Text_IO . Put_Line (Height'img); end Main;
http://libre.adacore.com
Text_IO is the p predefined Ada text Input/Output library
Procedures declared in library Text_IO and used in Main
© AdaCore under the GNU Free Documentation License
18
use Text_IO; Text IO;
with Text_IO; use Text_IO; procedure Main is Length : Integer := 8265; Width : Integer := 0252; H i ht : Integer Height I t := 8292 8292; begin Text_IO . Put_Line (Length'img); Text IO . Put_Line Text_IO Put Line (Width'img); Text_IO . Put_Line (Height'img); end Main;
http://libre.adacore.com
By putting a use clause you can (but don't have to)) omit the Text_IO prefix inside Main
© AdaCore under the GNU Free Documentation License
19
The ' img Attribute
with Text_IO; use Text_IO; procedure Main is Length : Integer := 8265; Width : Integer := 0252; H i ht : Integer Height I t := 8292 8292; begin Text_IO . Put_Line (Length ' img); Text IO . Put_Line Put Line (Width ' img); Text_IO Text_IO . Put_Line (Height ' img); end Main;
http://libre.adacore.com
' img is a predefined GNAT attribute Given an integer or floating point number X, X ' img returns its string representation • More on attributes later on •
© AdaCore under the GNU Free Documentation License
20
St Structure t off an Ad Ada Program P
General Structure of an Ada Program
with …;
with …;
with …;
with …;
with …;
with …; procedure Some_Main is … begin … end Some_Main; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
22
A Simple Example with Text_IO; use Text_IO; procedure Display (S : String; X X, Y : Integer) is begin Put_Line (S & " (" & X'img & ") = " & Y'img); end Display;
function Fact (N : Integer) return Integer is begin if N 0 then K := Integer’Last; -- K is set to the largest Integer end if; else K = X / Y; -- it is safe to divide by Y since it cannot be 0 Y := Y + 1; end if; end Checked_Divide;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
47
M More C/C C/C++/Java /J S Syntactic t ti Pitfalls Pitf ll
Is the Following Code Correct ? // If the signal ahead is clear then increase the speed. void o d increase c ease_speed_ speed if_sa safee ((intt speed, intt ssignal) g a) { if (signal == CLEAR); increase_speed (); }
This program compiles fine, but has a problem. Which one?
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
49
Bugs can Have Serious Consequences
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
50
Be Careful of Spurious Semicolons // If the signal ahead is clear then increase the speed. void o d increase c ease_speed_ speed if_sa safee ((intt speed, intt ssignal) g a) { if (signal == CLEAR); increase_speed (); }
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
51
The Ada Version is Always Safe -- If the signal ahead is clear then increase the speed speed. procedure increase_speed_if_safe (speed : integer; signal : integer) is begin if signal = CLEAR then increase_speed; end if; end increase_speed_if_safe;
If you write if signal = CLEAR then ; • You get a compiler error
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
52
More Bad Luck in C/C++/Java: Enumerations and Switch Statements enum Alert_Type {LOW, MEDIUM, HIGH, VERY_HIGH}; // C or C++. C++ Java does not have enumerations enumerations, you have to use ints instead void handle_alert (enum Alert_Type alert) { switch (alert) { case LOW: activate_camera (); case MEDIUM: send_guard (); case HIGH: sound_alarm (); } } void process_alerts () { handle_alert (2); …
This program compiles fine, but has a number of problems. Which ones? http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
53
Defects in the Previous Code
Don't forget break statements
C/C++/Java do not check that you have treated all cases in the switch
case labels can be integers or (values of) any enum type, not just enum Alert_Type which in most cases will be an error
http://libre.adacore.com
void handle_alert (enum Alert_Type alert) { switch it h (alert) ( l t) { case LOW: activate_camera (); break; case MEDIUM: send_guard (); break; case HIGH: sound_alarm (); break; case VERY_HIGH: alert_police (); break;; } } void process_alerts () { handle_alert (HIGH);
© AdaCore under the GNU Free Documentation License
54
Ada is Safer (and Less Verbose) type Alert_Type Alert Type is (LOW, (LOW MEDIUM MEDIUM, HIGH HIGH, VERY VERY_HIGH); HIGH); procedure Process_Alert (Alert : Alert_Type) is begin case Alert is when LOW => Activate Camera; Activate_Camera; when MEDIUM => Send_Guard; => when HIGH Sound_Alarm; when VERY_HIGH => _ ; Alert_Police; end case; end Process_Alert;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
N break No b k statements t t t
Ada will check that you have treated all cases in the case statement
Y can only l use an object bj t You of type Alert_Type
55
Combining Cases procedure Process_Alert Process Alert (Alert : Alert_Type) Alert Type) is begin case Alert is when LOW => Activate_Camera; when MEDIUM => Send Guard; Send_Guard; when HIGH | VERY_HIGH => Sound Alarm; Sound_Alarm; Alert_Police; end case; end Process_Alert; _ ;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
56
Using a Default Clause procedure Process_Alert Process Alert (Alert : Alert_Type) Alert Type) is begin case Alert is when LOW => Activate_Camera; when MEDIUM => Send Guard; Send_Guard; when others => Sound_Alarm; Alert Police; Alert_Police; end case; end Process_Alert;
Ada "when others" is equivalent to C/C++/Java "default", and takes away most of the benefit of the checking for all cases covered http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
57
Using a Range procedure Process_Alert Process Alert (Alert : Alert_Type) Alert Type) is begin case Alert is when LOW => Activate_Camera; when MEDIUM .. VERY_HIGH => Send Guard; Send_Guard; Sound_Alarm; Alert_Police; end case; end Process_Alert;
A range is a set of ordered values •
MEDIUM .. VERY_HIGH = MEDIUM, HIGH, VERY_HIGH
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
58
Enumeration Types in Ada type Alert is (LOW, MEDIUM, HIGH, VERY_HIGH); procedure P (B : Integer) is A : Alert; begin Compilation error A := B;
Enumerations are true types in Ada In C enums are just integers In C++ enums are implicitly converted to ints (not from ints) // C++ C enum Alert {LOW, MEDIUM, HIGH, VERY_HIGH}; int k = LOW;; Alert a = 1; http://libre.adacore.com
// accepted p byy C++ // rejected by C++
© AdaCore under the GNU Free Documentation License
59
Java Does not Have Enumerations :( In Java you must use integers // Java public static final int LOW public static final int MEDIUM public static final int HIGH public static final int VERY_HIGH
http://libre.adacore.com
= 0; = 0; = 0; = 0;
© AdaCore under the GNU Free Documentation License
60
Ada Enumeration Types and Attributes
http://libre.adacore.com
Alert_Type ' First
LOW
Alert_Type ' Last
VERY_HIGH
© AdaCore under the GNU Free Documentation License
61
Predefined Enumerations in Ada
http://libre.adacore.com
type Boolean
is (False, True);
type Character
is (…, 'a', 'b', 'c', …);
© AdaCore under the GNU Free Documentation License
62
Predefined Enumerations: Examples function Is_Letter Is Letter (C : Character) return Boolean is begin return (C in 'a' .. 'z') or (C in 'A' .. 'Z'); end Is_Letter; Is Letter;
function Is_Arithmetic_Operator (C : Character) return Boolean is begin case C is when h '+' ' ' | ''-'' | '*' | '/' => return True; when others => return t F l False; end case; end Is_Arithmetic_Operator;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
63
C Conciseness i Versus V R Readability d bilit
Always Favor Readability What does the following mean: • • •
This is valid C/C++/Java It is very concise … … but not very readable
What does the following mean: • • •
http://libre.adacore.com
This is valid Ada It is less concise … … but very readable
© AdaCore under the GNU Free Documentation License
int x; int y; int z; … x = y---z--;
i t x : integer; y : integer; z : integer; … x := y - z; y := y - 1; z := z - 1; 65
Comment on
x=y y---z--; z ;
Any sensible C/C++/Java programmer would write x = y-- - z--; I still prefer the following more verbose style x = y - z; y--; z ; z--; … it is simpler to understand by the average programmer reading your code This depends on the organization you work in :) http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
66
Good Programming is Altruistic Other people read and work on your code Write yyour code so that others can read and work on it Readability is a function of the programmers in your group • Present AND future programmers
If you are in a group of gurus it is ok to prefer
x = y-- - z--;
In most organizations programmers are not gurus In this case
http://libre.adacore.com
x = y - z; y--; z ; z--;
is easier to read/ read/work ork on
© AdaCore under the GNU Free Documentation License
67
Conciseness and Non Determinism What does the following mean: • •
{ int k = 0; int v [10];
It compiles, but … … Its semantics are undefined
k = v [k++]; }
It could mean any one of the following (when written in Ada): declare K : Integer := 0; V : array (0 .. 9) of Integer; begin b i K := V (K); K := K + 1; … http://libre.adacore.com
declare K : Integer := 0; V : array (0 .. 9) of Integer; begin b i K := V (K); …
© AdaCore under the GNU Free Documentation License
declare K : Integer := 0; V : array (0 .. 9) of Integer; begin b i Erase_All_Hard_Disks; …
68
If Anybody Can Can'tt Read It Don't Don t Write It A piece of code is written once …. … but read and modified manyy manyy times C/C++/Java syntax favors conciseness over readability • This leads to bugs and wasted time in debugging • This means that software is more costly to develop or is buggy or both
Ada syntax favors readability • Ada compiler catches silly mistakes • Faster and cheaper p to pproduce correct code when written in Ada
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
69
C/C /J C/C++/Java T Type S System t
What is a Type? A type is characterized by: The set of values an expression of that type p yp can take The operations that can be applied to those values
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
71
Pre Defined and User Pre-Defined User-Defined Defined Types Some types can be pre-defined by the language • E.g. booleans, integers, characters, strings, etc
Pre-defined types come with pre-defined operations • E.g. for integers: additions, subtractions, etc.
Languages typically allow user-defined types and operations • User-defined operations are provided in the form of procedures and
functions
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
72
Objects Variables and Constants Objects, An object of a given type is a run-time entity (usually a piece of memory) containing values of the type
A variable is an object whose value can change
A constant is an object whose value cannot change after it has been initialized
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
73
Example An object with name w The object is a variable
memory
int w; w
defined integer type in C whose values go from int is a pre pre-defined INT_MIN to INT_MAX S Some off the th predefined d fi d operations ti that th t can be b applied li d to t int i t are: • Addition, subtraction, multiplication, division, remainder, etc.
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
74
Type Checking Type checking is the process that checks that programs conform to the typing rules of the language Type checking can be performed • Statically at compile-time • Dynamically D i ll att execution-time ti ti
A language is strongly typed if it prohibits • The application of an operation to an object that is not intended to support
the operation (assignment is considered an operation)
A language g g is weaklyy typed yp if it is not strongly g y typed yp http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
75
Strong Typing is Good It prevents many kinds of crashing bugs
It tells the programmer when she has mixed "apples" with oranges "oranges"
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
76
Some Examples Strongly (mainly statically) typed languages: • Ada, Eiffel, Java
Strongly dynamically typed languages • Scheme, Smalltalk
Weakly typed languages • C, C++
Completely untyped languages • assemblyy languages, g g , shell scripts p
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
77
Typing Problems Common to C/C++/Java typedef in C/C++ is a shorthand it does not define a new type No user-defined types • • •
S l (characters, ( h t i t l ) Scalars integers, reals) Pointers (e.g. there can only be a single pointer to an int type) Arrays (e.g. there can only be a single array of int type)
Implicit conversions from integers to reals Weak overflow semantics rules for signed integers Missing types • • • • • http://libre.adacore.com
Enumerations in Java ((not full types yp in C/C++)) Character types in C/C++ Fixed points Unsigned integers in Java Pointers to functions in Java © AdaCore under the GNU Free Documentation License
78
Example of C/C++/Java Type System Weakness No User-Defined Scalar Types
C/C++ Example typedef int Time; typedef int Distance; typedef int Speed; … const Speed SAFETY_SPEED SAFETY SPEED = 120; … void increase_speed (Speed s); … void check_speed (Time t, Distance d) { Speed s = d/t; if (s < SAFETY_SPEED) increase_speed (t); } void perform_safety_checks () { Time t = get_time (); Distance d = get_distance (); … check_speed h k d (d (d, t)t); } http://libre.adacore.com
The program to the left compiles fine There is something wrong with it What ?
© AdaCore under the GNU Free Documentation License
80
Bugs can have Disastrous Consequences
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
81
What's What s Wrong with C/C++ typedef int Time; typedef int Distance; typedef int Speed; … const Speed SAFETY_SPEED SAFETY SPEED = 120; … void increase_speed (Speed s); … void check_speed (Time t, Distance d) { Speed s = d/t; if (s < SAFETY_SPEED) increase_speed (t); } void perform_safety_checks () { Time t = get_time (); Distance d = get_distance (); … check_speed h k d (d (d, t)t); } http://libre.adacore.com
Program g compiles p fine but has 2 serious flaws that go undetected FLAW 1: t is a Time increase_speed() takes a Speed parameter • Time and Speed are conceptually different, they should not be mixed up • •
FLAW 2: Di t t hhave Distance andd Ti Time parameters been inverted • Time and Distance are conceptually different,, theyy should not be mixed upp •
C/C++ provide NO HELP to the programmer in detecting these mistakes
© AdaCore under the GNU Free Documentation License
82
Things are Even Worse in Java There are no typedef yp in Java Everything must be an int
typedef are useful for documentation purposes typedef could be used to perform sanity checks during code walkthroughs or with simple tools
This problem is particularly severe in Java given that many API calls have several indistinguishable int parameters: •
final int SAFETY_SPEED SAFETY SPEED = 120; … void check_speed (int t, int d) { int s = d/t; if (s < SAFETY_SPEED) increase_speed (t); } void increase_speed (int s) { … } void perform_safety_checks () { int t = gget_time _ (); int d = get_distance (); … check_speed (d, t); }
AdjustmentEvent (Adjustable source, int id, int type, int value)
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
83
What About Ada? You can write the same buggy code in Ada, but …
… Ada has two lines of defense th t do that d nott exist i t in i C/C++ C/C or Java to protect the programmer • User defined types • Parameter associations
http://libre.adacore.com
-- Buggy ggy code. DON'T write this SAFETY_SPEED : constant Integer := 120; … procedure Increase_Speed Increase Speed (S : Integer); … procedure Check_Speed (T : Integer; D : Integer) is S : Integer := D / T; begin if S < SAFETY_SPEED then Increase_Speed (T); end if; end Check_Speed; p ; procedure Perform_Safety_Checks is T : Integer := Get_Time; g := Get_Distance;; D : Integer begin … Check_Speed (D, T); end Perform_Safetyy_Checks;;
© AdaCore under the GNU Free Documentation License
84
Defining New Types in Ada Users can define their own types in Ada In C/C++/Java users can onlyy define struct/union/class types yp • No user-defined scalar, pointer or array types
-- Example of integer type definition in Ada type Time
is range 0 .. 33_600; 600;
type Distance is range 0 .. 1_000; type Speed
http://libre.adacore.com
is range 0 .. 4_000;
© AdaCore under the GNU Free Documentation License
85
User Defined Integer Types in Ada Each E h user defined d fi d integer i t type t introduces i t d a new type type yp Time
is range g 0 .. 3_600;;
This new type is NOT a synonym of Integer
type Distance is range 0 .. 1_000; type Speed
is range 0 .. 4_000;
Each user defined integer type gives its bounds, i.e. the values any object of this type can take • •
http://libre.adacore.com
Time ' First = 0 Time ' Last = 3_600
© AdaCore under the GNU Free Documentation License
86
Ada is Strongly Typed (1 of 2) ttype Time Ti iis range 0 .. 33_600; 600 type Distance is range 0 .. 1_000; type Speed is range 0 .. 4_000; SAFETY_SPEED : constant Speed := 120; procedure Increase_Speed Increase Speed (S : Speed); procedure Check_Speed (T : Time; D : Distance) is Compilation p S : Speed ::= D / T; error begin if S < SAFETY_SPEED then Compilation p Increase Speed (T); Increase_Speed error end if; end Check_Speed; …
http://libre.adacore.com
When yyou define the p proper p types yp the Ada compiler catches the errors To mix different types you must use explicit conversions in Ada
D is of type Distance, T is of type Time, S is of type Speed •
Only objects of the same type can be mixed together in this fashion
Increase_Speed is expecting a Speed parameter not a Time
© AdaCore under the GNU Free Documentation License
87
Ada is Strongly Typed (2 of 2) type Time is range 0 .. 3_600; type Distance is range 0 .. 1_000; type Speed is range 0 .. 44_000; 000; … procedure Check_Speed (T : Time; D : Distance); … procedure Perform_Safety_Checks is T : Time := Get_Time; D : Distance := Get_Distance; _ ; begin … Compilation Check_Speed (D, T); error end Perform_Safety_Checks;
http://libre.adacore.com
Parameters switched
© AdaCore under the GNU Free Documentation License
88
The Correct Ada Version type Time is range 0 .. 3_600; type Distance is range 0 .. 11_000; 000; type Speed is range 0 .. 4_000; SAFETY_SPEED : constant Speed := 120; procedure Increase_Speed (S : Speed); procedure Check_Speed (T : Time; D : Distance) is S : Speed := Speed ( Integer(D) / Integer (T)); begin if S < SAFETY_SPEED then Increase_Speed (S); end if; end Check_Speed; procedure Perform_Safety_Checks is T : Time := Get Get_Time; Time; D : Distance := Get_Distance; begin … Check_Speed (T, D); end Perform_Safety_Checks; http://libre.adacore.com
You must convert D and T to Integer to perform the division And then convert the result to type Speed
© AdaCore under the GNU Free Documentation License
89
But What About? type A_Type A Type is …;;
How do you know it was
procedure Safe_Copy (Source : A_Type; Target : A_Type); procedure Try is X : A_Type := …; Y : A_Type := …; begin Safe_Copy (X, Y); … end Try;
http://libre.adacore.com
Safe_Copy (X, Y) and not Safe_Copy (Y, X)
You don't. That's why Ada provides name parameters
© AdaCore under the GNU Free Documentation License
90
Ada has Named Parameters type A_Type is …; procedure p ocedu e Sa Safee_Copy Copy (Sou (Source ce : A_Type; ype; Target a get : A_Type); ype); procedure Try is X : A_Type yp := …; Y : A_Type := …; begin Safe_Copy (Source => X, Target => Y); … end Try;
Named parameter
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
91
Avoiding Parameter Confusion in Ada Summary: Two lines of defense
User defined types
Named parameters
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
92
Example of C/C++/Java Type System Weakness Signed Integer Overflow Semantics
Overflow in C/C++/Java #include void compute () { int k = INT_MAX; k = k + 1; }
In C/C++ signed g integer g overflow is undefined,, anything y g can happen pp • All known implementations "wrap around"
In Java wrap around semantics are part of the language
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
94
Overflow in Ada procedure Compute is K : Integer := Integer'Last; begin g Exception raised K := K + 1; at execution end Compute; time
EVERY time there is an integer g overflow in Ada an exception p is raised
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
95
Example: Overflow in Action in Ada In GNAT you have to use the switch -gnato to ask for integer overflow checking
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
96
The Pernicious Effects of Wrap-Around Semantics: A Java Example final int RADIO_PORT = …; void o d ope open ((intt po port) t) {{…}} void send (int port, byte data) {…} void close (int port) {…} void send_bytes (byte first_byte, byte last_byte) { open (RADIO_PORT); for (byte b = first_byte; b Put_Line (("Raised exception p : " & Exception p _Name ((E)); )); Put_Line (Symbolic_Traceback (E)); end Checks; © AdaCore under the GNU Free Documentation License
111
-bargs: Program binder arguments: -E: give exception tracebacks -cargs: Compiler arguments: -g: debugging on -gnatl: print out a program listing -gnato: overflow checks on
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
112
What Happens at Execution Time with Ada.Exceptions; with GNAT.Traceback.Symbolic; with Text_IO;
use Ada.Exceptions; use GNAT.Traceback.Symbolic; use Text_IO;
procedure Checks is Internal Error : Exception; Internal_Error
b
d
http://libre.adacore.com
procedure Foo is begin raise Internal_Error; Internal Error; end Foo;
a
procedure Bar is begin Foo; end Bar;
c
beg -- oof C begin Checks ec s Bar; e exception when E : others => Put_Line (("Raised exception p : " & Exception p _Name ((E)); )); Put_Line (Symbolic_Traceback (E)); end Checks; © AdaCore under the GNU Free Documentation License
113
Catching a Predefined Exception with Text_IO; use Text_IO; procedure Checks is A : Integer I t := Integer I t ’ Fi First;t begin A := A - 1; exception when Constraint_Error => Put_Line (“Overflow occurred”); end Checks;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
114
Catching Your Own Exceptions with Text_IO; use Text_IO; procedure Checks is p Internal_Error : Exception; procedure Foo is begin raise Internal_Error; end Foo; procedure Bar is begin Foo; end Bar; begin -- of Checks Bar; exception when Internal_Error => Put_Line (“problem occurred”); when others =>> Put_Line (“some other exception”); end Checks; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
115
Catching an Exception Where You Want procedure Checks is … begin -- of Checks : : : : : : : : : : : : : : : end Checks; http://libre.adacore.com
to catch some exception in a region of code without exiting from the subprogram you can use a declare block
© AdaCore under the GNU Free Documentation License
116
Example of a Declare Block procedure Calc (A, B : Float) is C, D : Float; begin … declare Old_C : Float := C; begin C := A * B; D := C ** 2; exception when Constraint_Error => C := Old_C; D := 0.0;; end; … end Calc; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
117
A Array Pitf Pitfalls ll in i C
Arrays in C No real arrays in C An arrayy is jjust a p pointer to a chunk of memoryy #include int main () { char *str = "bugy"; printf ("%c\n", 0 [str]); printf ("%c\n", * (str+1)); printf ("%c\n", * (2+str)); printf i tf ("% ("%c\n", \ " strt [3]); [3]) }
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
119
C "Arrays" Arrays are Just Pointers: No Safety void display_arr (char *name, char *arr, int n)) { int k; printf ("%s = ", name); for (k = 0; k < n; k++) printf ("%c" ( %c , arr [k]); printf ("\n"); }
#include #include char x [4] = {'A', 'B', 'C', 'D'}; char y [4] = {'E', { 'F', 'G', G 'H'}; } char z [4] = {'I', 'J', 'K', 'L'}; … i t main int i () { char *p; display(); p = x; memcpy (p, "0123456789", 10); display (); x [6]= '?'; display ();
void display () { display_arr ("x", x, 4); display_arr ("y", y, 4); display arr ("z" display_arr ( z , z, z 4); printf ("------------\n"); }
} http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
120
What Does the C Standard Say? … char x [4] = {'A' { A , 'B' B , 'C' C , 'D'}; D }; char y [4] = {'E', 'F', 'G', 'H'}; char z [4] = {'I', 'J', 'K', 'L'}; … int main () { char *p;
Set p to the address of x
Copy "0123456789" 0123456789 in the 10 consecutive memory locations pointed by p
display(); p = x; memcpy (p, "0123456789", 10); display (); x [6]= '?'; di l () display (); } http://libre.adacore.com
Result is undefined since x is a pointer that points to 4 consecutrive preallocated bytes in memory, nott 7 compiler is free to do what it wants
© AdaCore under the GNU Free Documentation License
121
What Happens in Practice
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
122
What Happens in Memory: Allocation #include #include char x [4] = {{'A' A , 'B' B , 'C' C , 'D'}; D }; char y [4] = {'E', 'F', 'G', 'H'}; char z [4] = {'I', 'J', 'K', 'L'}; … int main () { char *p;
A
B
C
D
E
F
G
H
I
J
K
L
x[0]
x[1]
x[2]
x[3]
y[1]
y[2]
y[3]
y[4]
z[0]
z[0]
z[2]
z[3]
display(); p = x; memcpy py (p (p, "0123456789", 10); ) display (); x [6]= '?'; display (); } http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
123
Pointer Copy #include #include char x [4] = {'A' { A , 'B' B , 'C' C , 'D'}; D }; char y [4] = {'E', 'F', 'G', 'H'}; char z [4] = {'I', 'J', 'K', 'L'}; … int main () { char *p; display(); p = x; memcpy py (p (p, "0123456789", 10); ) display (); x [6]= '?'; display ();
A
B
C
D
E
F
G
H
I
J
K
L
x[0]
x[1]
x[2]
x[3]
y[1]
y[2]
y[3]
y[4]
z[0]
z[0]
z[2]
z[3]
p
} http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
124
memcpy #include #include char x [4] = {'A' { A , 'B' B , 'C' C , 'D'}; D }; char y [4] = {'E', 'F', 'G', 'H'}; char z [4] = {'I', 'J', 'K', 'L'}; … int main () { char *p; display(); p = x; memcpy py (p, (p "0123456789 0123456789", 10); ) display (); x [6]= '?'; display ();
0
1
2
3
4
5
6
7
8
9
K
L
x[0]
x[1]
x[2]
x[3]
y[1]
y[2]
y[3]
y[4]
z[0]
z[0]
z[2]
z[3]
p
} http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
125
x[6] = '?' ? #include #include char x [4] = {'A' { A , 'B' B , 'C' C , 'D'}; D }; char y [4] = {'E', 'F', 'G', 'H'}; char z [4] = {'I', 'J', 'K', 'L'}; … int main () { char *p; display(); p = x; memcpy py (p (p, "0123456789", 10); ) display (); x [6]= '?'; display ();
0
1
2
3
4
5
?
7
8
9
K
L
x[0]
x[1]
x[2]
x[3]
y[1]
y[2]
y[3]
y[4]
z[0]
z[0]
z[2]
z[3]
p
} http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
126
C and Arrays: Summary No real arrays
Very low level
Fundamentally unsafe mechanism
Too many ways of expressing the same thing
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
127
What about C++ and Java C++ • Same problem as in C • You can redefine the "[[ ]" ] operator in C++ for class types thereby
providing your own checks and semantics. However this makes code hard to read since when you see something like s [k] it does not mean any more what you ve been used to by many years of C and makes the you've code hard to understand if used in an uncontrolled fashion
Java • Has real arrays • Java model inspired from Ada • Difference between Java and Ada is that Java arrays MUST start at index
0, Ada can have arbitrary bounds
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
128
Arrays in Ada Ada has real arrays (1-dimensional and multi-dimensional)
Ada array can have its size determined at run-time • Local variable length arrays are allowed in the latest C standard (C99)
Ada array bounds can be arbitrary, lower bound does not have to start at 0
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
129
One of a Kind Arrays procedure Compute (N : Integer) is
In Ada Arrays can have arbitrary bounds
A : array (1 .. N) of Float; begin g … end Compute;
http://libre.adacore.com
The bounds can be dynamic values
© AdaCore under the GNU Free Documentation License
130
Typed Arrays procedure Compute (N : Integer) is type Arr is array (Integer range ) of Float; A : Arr (1 .. N) := (others => 9); B : Arr := A; C : Arr (11 .. 20) := (1, 2, others => 0); begin g C := A; C (15 .. 18) := A (5 .. 8); end Compute;
B takes its bounds from A
C'L th //= A'L th then th If C'Length A'Length Constraint_Error is raised
If A'Last < 8 then Constraint_Error is raised http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
131
Arrays in Ada are Safe If you try to index a non-existent arry position, a Constraint_Error exception is raised procedure Checks is A : arrayy ((1 .. 100)) of Integer; g begin A (101) ::= 1; end Checks;
http://libre.adacore.com
Exception raised
© AdaCore under the GNU Free Documentation License
132
Example of 1 1-Dim Dim Array Attributes Given A some array object • A : array (10 .. 99) of Integer;
http://libre.adacore.com
A ' First
10
A ' Last
99
A ' Length
90
A ' Range
10 .. 99
© AdaCore under the GNU Free Documentation License
133
Ada Arrays are Powerful: No Need to Pass Array Bounds as in C/C++/Java procedure Calc is type Vector is array (Natural range )) of Float; function Max (V : Vector) return Float is M : Float := Float ’ First; begin for K in V ’ Range loop if V (K) > M then M := V (K); end d if if; end loop; return M; end Max; V1 : Vector := (1.0, 2.0, 3.0); -- V'First = 0 and V'Last = 2 V2 : Vector (1 .. 100) := (1.0, 2.0, others => 5.0); X : Float := Max (V1); -- X = 3.0 Y : Float := Max (V2); -- Y = 5.0 begin … end Calc; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
134
Ada String Predefined Array Type type String is array (Positive range ) of Character; R : String (1 .. 10); S : Stringg := ((‘H’,, ‘e’,, ‘l’,, ‘l’,, ‘o’); ); T : String := “Hello”; Q : String := : S & “ “ & T & “ you you”;; -- Q = "Hello Hello you"
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
135
R Records d and d Pointers P i t in i Ada Ad
Record Types type Date D is i record d Day : Positive range 1 .. 31; Month : Positive range 1 .. 12; Year : Integer; end record; D : Date := (3, 9, 1975); A : Date ::= (Day =>> 31 31, Month =>> 12 12, Year =>> 1999); B : Date := A; Y : Integer := B . Year;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
137
Pointers and Records 3 9 type Node; type Node_Ptr is access Node; type Node is record D : Date := (1, 1, 1900); Next : Node_Ptr; end record;
1975
1 1
P1 : Node_Ptr := new Node; P2 : Node_Ptr N d P := new Node N d ’ ((3, ((3 99, 19 1975), ) P1) P1);
1900 null
Memory http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
138
N : Node := ((31, 12, 1999), null); P3 : Node_Ptr := new Node ’ (N);
31 12 1999 null
Memory http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
139
Accessing Record Fields: A Simple Rule If P is a pointer to a record then P.all
points to the WHOLE record
P.Field
points to Field in the record
Note: P.Field P Field
is the same as
P all Field P.all.Field
type Node is record D : Date ::= (1, 1, 1900); Next : Node_Ptr; end record; P : Node_Ptr := new Node; A_Date A Date : Date := P.D; P D; A_Node : Node_Ptr := P.Next; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
140
Parametrized Records: Discriminants type Q_Array (Positive range ) of Integer; type Queue (Max_Size : Positive) is record First : Positive := 1; Last : Positive := 1; Size : Natural := 0; Q : Q_ Q Arrayy ((1 .. Max_Size); ); end record; X : Queue (4); -- X.Max_Size X Max Size = 4 Y : Queue;
http://libre.adacore.com
Compilation Error Value for Max_Size Max Size missing
© AdaCore under the GNU Free Documentation License
141
P Parameter t P Passing i in i C, C Java J and d Ada Ad
Two Parameter Passing Modes in C/Java By value
By constant value
In C++ there are additional modes • By reference • By constant reference
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
143
By Value The parameter can be changed inside the function but the value of the original parameter is not modified void copy (int x, int y) { x = y; } void tryy () { int a = 0; int b = 9; copy (a, b); // a == 0 here }
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
144
By Constant Value In C void copy (const int x, const int y) { x = y; Compilation error }
In Java void copy (final int x, final int y) { x = y; Compilation error }
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
145
Changing the Actual Parameter In Java • There is NO way to change the value of a scalar parameter - You have to do it yourself by hand …
• For a record ((class)) or arrayy p parameter yyou can onlyy change g the components p • This is a problem: Java really makes the programmer's life hard here
In C t a pointer i t bby hhandd andd use th • Y You hhave tto create thatt • The programmer must perform tedious bookkeeping by specifying - *p and &s • This also makes the code hard to change void foo (int *p); … int s; foo (& s); http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
146
Three Parameter Passing Modes in Ada in
procedure Open_File (X : String); procedure Open_File (X : in String);
• It's the default mode, the in can be omitted
function Log (X : Float)
• Inside the procedure or function X is a constant initialized by the value of the actual parameter
return Float;
function Log (X : in Float) return Float;
• Functions can only have parameters of mode i in out
procedure Increment (X : in out Float);
• Inside the procedure X is a variable initialized by the value of the actual parameter • The actual parameter is updated with the last value of X when the procedure terminates. outt
procedure Copy (Y : Float; X : out Float);
• Inside the procedure X is an uninitialized variable • The actual parameter is updated with the last value of X when the procedure terminates
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
147
Example: Mode "in" in
function Log (X : Float) return Float is begin X ::= 1.0; Compilation error … X is a constant inside Log end Log;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
148
Example: Mode "in in out" out procedure A_Test is
Note: In Ada You can nest Note: functions & procedures
procedure Increment (X : in out Float) is begin X := X + 1.0; end Increment; Value : Float := 9.0; begin -- Value = 9.0 here ( ); Increment (Value); -- Value = 10.0 here end A_Test;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
149
Example: Mode "out" out procedure A_Test is procedure Copy (Y : Float; X : out Float) is begin X := Y; end Copy; Value : Float; begin -- Value is uninitialized here py ((10.0,, Value); ); Copy -- Value = 10.0 here end A_Test;
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
150
Ada Offers a Comprehensive Scheme for Safe Low-Level Programming
PSW Example S stem Mask System 0
Protection Key
unused n sed 7
8
11
12
15 16
Machine State
n sed unused 19 20
23
Represent the following program status word (PSW): PSW is i 24 bits bit Bits 0 to 7 contain a 7 bit system mask Bits 12 to 15 contain a 4 digit protection key Bits 20 to 24 contain the status flags g of the machine for the program p g •
The fours flags are called: A, M, W and P
All other bits are unused
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
152
The PSW Type in Ada System y Mask 0
7
type y State type Byte_Mask type State_Mask
Protection Key
unused 8
11
12
Machine State
unused
15 16
19 20
23
is ((A, M, W, P); ) is array (0 .. 7) of Boolean; is array (State) of Boolean;
type Program_Status_Word Program Status Word is record System_Mask : Byte_Mask; Protection_Key : Integer range 0 .. 15; Machine_State : State_Mask; end record; for Program_Status_Word use record System Mask System_Mask at 0 range 0 .. 7; Protection_Key at 0 range 12 .. 15; Machine_State at 0 range 20 .. 23; end record; for Program_Status_Word ' Size use 3 * System.Storage_Unit; http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
153
Accessing PSW Fields in Ada is … Simple … type Program_Status_Word is record S t System_Mask M k : Byte_Mask; B t M k Protection_Key : Integer range 0 .. 15; Machine_State : State_Mask; end record; …
Safe Efficient
PSW
: Program_Status_Word := …;
Keyy : Integer g M_State : Boolean Mask_3 : Boolean
http://libre.adacore.com
:= PSW . Protection_Key; y := PSW . Machine_State (M); := PSW . System_Mask (3);
© AdaCore under the GNU Free Documentation License
154
There is more in Ada to help with safe and efficient low-level programming than just the previous example
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
155
Interfacing Ada with C Is Part of the Ada Standard
"Ada Ada Can Call C C" You can call C routines from Ada code -- Ada … procedure Make_Dir (Dir_Name : String) is C_Dir_Name : String := Dir_Name & ASCII.NUL;
/* C */ int mkdir (const char *s) { … }
function mkdir (Dir_Name : String) return Integer; pragma Import (C, mkdir, "__gnat_mkdir"); begin if mkdir (C_Dir_Name) /= 0 then raise Directory_Error; Directory Error; end if; end Make_Dir; … http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
157
"C C Can Call Ada" Ada You can call Ada routines from C code -- Ada … procedure My_Example (X, Y : Integer); pragma Export (C, My_Example, "_ada_example"); … /* C */ extern void _ada_example (const int x, y); void try_it () { _ada_example (3, 4); }
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
158
There is more to interfacing than these simple examples
http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
159
S Summary: Better B tt S Safe f th than Sorry S
Language Safety and Security
unsafe assembly
http://libre.adacore.com
C
C++ C
Java
© AdaCore under the GNU Free Documentation License
Ada
safe
161
Summary A good d programming i language l • Encourages the writing of correct software • Helps p in detectingg errors
C/C++/Java • Encourage the writing of concise code not correct software • C/C++ provide no help in detecting errors • Java provides some help
Ada (and other languages such as Eiffel) • Encourage the writing of correct software • Provide help in detecting errors http://libre.adacore.com
© AdaCore under the GNU Free Documentation License
162