From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE, MSGID_SHORT autolearn=no autolearn_force=no version=3.4.4 Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site sftor.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!mhuxv!mhuxf!mhuxm!sftig!sfsup!sfmag!sftor!cw From: cw@sftor.UUCP (C.S.Wetherell) Newsgroups: net.lang.ada Subject: Two characteristic programming errors in Ada Message-ID: <951@sftor.UUCP> Date: Fri, 4-Apr-86 08:36:35 EST Article-I.D.: sftor.951 Posted: Fri Apr 4 08:36:35 1986 Date-Received: Sat, 5-Apr-86 12:29:32 EST Distribution: net Organization: AT&T Bell Laboratories, Summit N.J. List-Id: While porting some programs from the Simtel20 archives to our new compiler, I had some difficulty with one of them. Upon investigation, I discovered two subtle but characteristic misuses of Ada. I am sure they are quite common, so I will protect the author. Consider the following procedure declaration (ignore its innards for the moment) procedure Does_A_Check(Formal : in out NATURAL); and the skeletal calling routine with Does_A_Check; procedure Im_A_Caller is Actual : NATURAL; begin Does_A_Check(Actual); end; When this pair was linked and executed, a constraint exception was raised at the point of call. [This happened to be particularly mystifying in the ported program, because the program was carefully taking care of all exceptions and I couldn't tell at first exactly what was causing the program to fail. Some embedding of trace statements uncovered the difficulty after a bit.] Of course, the reason the constraint error was raised was that variable Actual in Im_A_Caller was not initialized; there is no requirement that the initial value of a variable be within its declared bounds (with exception of access types, of course). Since formal in-out parameters are checked for constraints at procedure entry, a constraint error was raised. I can only assume that the particular program had always been compiled and executed on a system where the initial values were within bounds; this is, of course, an example of a bug common to other languages as well. However, there is a second bug in the program. Let us now consider the body of Does_A_Check: procedure Does_A_Check(Formal : in out NATURAL) is begin Formal := 0; ... Something := ... Formal ...; ... end; Notice that the first thing Does_A_Check executes is an initializing assignment to Formal; the routine really doesn't care about the in-bound value of the actual argument at all. In fact, the only reason that Formal is declared "in out" is so that it can be used on the right-hand side of some statements. Now, the Ada rule is that an "out" parameter cannot be so used; the parameter may have an undefined value at some places of such usage and the rules about no right-hand usage keep the compiler from having to do a flow analysis to determine if a particular usage is after a definition. Here, the programmer, to save declaring a local variable, just made Formal "in out"; then it can be used on the right. But the cost is unexpected constraint errors or extra work for the caller; after all, the caller doesn't know (in theory) why the formal parameter is "in out" and may have to go to considerable trouble to guarantee that the actual argument has an acceptable value; this is disturbing when the formal doesn't really need the initial value. The moral seems to be to use "in out" parameters only when the called routine actually needs the initial value; otherwise, use a paradigm like procedure Does_A_Check(Formal : out NATURAL) is Local : NATURAL; begin Local := 0; -- yes, this could be done in the declaration. ... Something := ... Local ... ... Formal := Local; return; end Does_A_Check; Finally, I might note that this problem was uncovered partly because our compiler temporarily is storing characters in 16-bits while a little part of our code generator is undergoing additional education about the differences between signed and unsigned bytes. One version of the problem was using characters instead of NATURAL's. If the Actual from above had been an 8-bit character, it might have been automatically truncated to within the constraints; as a 16-bit character, it was not. There is no guarantee in Ada about the sizes of types beyond the rules governing type declarations; this particular stretch of code was mildly unrobust in the face of changing sizes Charles Wetherell AT&T Information Systems Summit NJ