DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
G2++ Tutorial - G2++(3C++)

Pathological Record Definitions

For technical reasons, initial capacity specifications in G2++ record definitions are sometimes ignored. Fortunately, g2++comp(1C++) warns about these cases and even suggests corrective action.

Specifically, initial capacity specifications in either of the two forms discussed in the last section, ``Adding Builtin C Types to the Repertoire of G2++ Types'', are honored only for strings or arrays that occur as members of an immediately enclosing structure. This condition guarantees that the string or array has a name (names act as "carriers" of initial capacity information).

Each of the following four record definitions fails to satisfy the condition:

   case_1.g
           case_1a 100
           case_1b
                   100     LONG
           case_1c *(100)
           case_1d
                   *(100)  LONG

In the code generated by g2++comp(1C++), CASE_1A and CASE_1C are strings, and CASE_1B and CASE_1D are arrays; since none of these strings or arrays is the member of an immediately enclosing structure, their initial capacity specifications are ignored. The following code is therefore problematic:

       #include "case_1.h"
       main(){
           CASE_1A a;
           CASE_1B b;
           CASE_1C c;
           CASE_1D d;
           a.pad(100,'x');  inefficient
           b[99] = 99;      core dump?
           c.pad(100,'x');  inefficient
           d[99] = 99;      core dump?
       }

The corrective action is suggested by the compiler:

   g2++comp: file 'case_1.g': path 'case_1a.100' warning:
       100 will not be used as the initial string size; for
       proper preallocation, use a constructor argument,
       e.g., CASE_1A x(Stringsize(100));
   g2++comp: file 'case_1.g': path 'case_1b.100' warning:
       100 will not be used as the initial array size; for
       proper preallocation, use a constructor argument,
       e.g., CASE_1B x(100);
   g2++comp: file 'case_1.g': path 'case_1c.*(100)'
       warning: 100 will not be used as the initial string
       size; for proper preallocation, use a constructor
       argument, e.g., CASE_1C x(Stringsize(100));
   g2++comp: file 'case_1.g': path 'case_1b.*(100)'
       warning: 100 will not be used as the initial array
       size; for proper preallocation, use a constructor
       argument, e.g., CASE_1D x(100);

Here's the client code after taking the corrective action:

       #include "case_1.h"
       main(){
           CASE_1A a(Stringsize(100));
           CASE_1B b(100);
           CASE_1C c(Stringsize(100));
           CASE_1D d(100);
           a.pad(100,'x');  efficient
           b[99] = 99;      OK
           c.pad(100,'x');  efficient
           d[99] = 99;      OK    }

The same problem can occur at deeper levels within a structure:

   case_2.g
           case_2a
                   x       LONG
                   y
                           *       100
           case_2b
                   x       LONG
                   y
                           50
                                   100     LONG

In the code generated by g2++comp(1C++), the elements of the arbitrary size array CASE_2A::y are anonymous; the 100 will therefore be ignored as an initial capacity specification. In CASE_2B::y, the elements of the array y, themselves arrays, will not have 100 elements preallocated for the same reason. The following client code therefore exhibits problematic behavior:

       #include "case_2.h"
       main(){
           CASE_2A a;
           CASE_2B b;
           a.y[10].pad(100,'x');  inefficient
           b.y[49][99] = 99;     core dump?
       }

The earlier corrective action -- specifying a constructor argument -- is not available in this case; instead, we must modify the record definition itself. This is suggested by the compiler:

   g2++comp: file 'case_2.g': path 'case_2a.y.0' warning:
       100 will not be used as the initial string capacity;
       consider redefining the element type as a structure
   g2++comp: file 'case_2.g': path 'case_2b.y.0' warning:
       100 will not be used as the initial array size;
       consider redefining the element type as a structure

Taking the suggested action gives the following record definitions:

   case_2.g
           case_2a
                   x       LONG
                   y
                           *
                                   x       100
           case_2b
                   x       LONG
                   y
                           *
                                   x
                                           100     LONG

Here is the corrected client code:

       #include "case_2.h"
       main(){
           CASE_2A a;
           CASE_2B b;
           a.y[10].x.pad(100,'x');  efficient
           b.y.[49].x[99] = 99;      OK
       }

These record definitions entail a slight runtime overhead which will be more than offset by the efficiency gained by honoring initial capacity specifications.


Next topic: Using G2++ with User-Defined Types
Previous topic: The Initial Capacity of Strings and Arrays

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004