Programming in the Small: C/C++/Java Pitfalls & Ada Benefits

7 downloads 760 Views 855KB Size Report
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

Suggest Documents