smithd@software.org (Doug Smith) (04/09/91)
-- According to the Ada LRM, 13.5.8, address clauses should not be used to achieve overlays -- of objects or overlays of program units. However, I have unwittingly used just that -- approach to hide information, create freelists of allocated memory, etc. So far the -- compilers I have used behave as expected, with one inconsistency. -- Should an object that has an address clause also have default initializations applied? -- Explicit initializations are not a big problem (I can control that). But several times -- now, my concientious attempts at providing reasonable default initialization while -- going to extremes to hide implementation details has created portability problems. -- The DEC Ada compiler does the initialization. The Verdix compiler (several versions -- old now) does not. My first thought was that the DEC Ada compiler was correct, but -- I'm not so sure. If this feature were not so convenient and powerful, who would care? -- I invite your comments on which behavior you believe is appropriate. Keep in mind that -- this is a very simplified example of the technique. (Unchecked_Conversion does not -- work in other situations I have encountered!) with Text_IO; with System; procedure Test is begin Try_Access_Types: declare type Pointer is access Integer; Pointer_Value : Pointer := new Integer; Pointer_Value_2 : Pointer; -- Overlay !!! for Pointer_Value_2 use at Pointer_Value'Address; begin if Pointer_Value_2 = null then Text_IO.Put_Line ("Your compiler initializes pointer " & "declarations even with representation clauses."); else Text_IO.Put_Line ("Your compiler fails to initialize pointer " & "declarations with representation clauses."); end if; end Try_Access_Types; Try_Record_Types: declare type R is record I : Integer := 13; end record; R_Value : R := R'( I => 17 ); R_Value_2 : R; -- Overlay !!! for R_Value_2 use at R_Value'Address; begin if R_Value_2.I = 13 then Text_IO.Put_Line ("Your compiler initializes record component " & "declarations even with representation clauses."); elsif R_Value_2.I = 17 then Text_IO.Put_Line ("Your compiler fails to initialize record component " & "declarations with representation clauses."); end if; end Try_Record_Types; end;
sampson@cod.NOSC.MIL (Charles H. Sampson) (04/10/91)
In article <1991Apr8.174020.8176@software.org> smithd@software.org (Doug Smith) writes that he is violating the LRM, 13.5(8) by using address clauses to overlay data. He then questions some of the execution results he is get- ting, particularly when it comes to initializing these data. His question is: Can these data be reliably initialized as part of their declaration, or should they be initialized dynamically? To illustrate the problem, he gives two sim- ilar code fragments, of which the following is one. >with Text_IO; >with System; > >procedure Test is >begin > > Try_Access_Types: > declare > > type Pointer is access Integer; > > Pointer_Value : Pointer := new Integer; > Pointer_Value_2 : Pointer; -- Overlay !!! > for Pointer_Value_2 use at Pointer_Value'Address; > > begin > if Pointer_Value_2 = null then > Text_IO.Put_Line ("Your compiler initializes pointer " & > "declarations even with representation clauses."); > else > Text_IO.Put_Line ("Your compiler fails to initialize pointer " & > "declarations with representation clauses."); > end if; > end Try_Access_Types; > >end; His complaint is that this code executes differently on different compilers. The reason for the erratic behaviour is that the above code is erroneous, as Smith has pointed out, and the effect of executing erroneous code is un- predictable [LRM 1.6(7)]. Looking at the code, I would expect the generated code to first initialize Pointer_value, then initialize Pointer_value_2, overwriting Pointer_value's value with NULL, which is apparently what happens in most cases. However, wondrous things sometimes happen deep inside com- pilers, and the LRM doesn't require compiler writers to spend time on making sure that the obvious thing happens to erroneous programs. One possibility that comes to mind in this case is that some compilers accumulate blocks of static initial values out of line, and initialization begins by moving these blocks into position on the stack, followed by evalua- ting any non-static initial values. With this approach, Pointer_value_2's NULL is static and it will be overwritten after Pointer_value's allocator is evaluated. Charlie