One pill makes you larger
And one pill makes you small
After fifty years, PL/I still retains it's capacity to astound me.
Most recently I have been poking around in the dusty corners of the based storage class.
We all know its usefulness for, for example, list processing, allocating and traversing a linked list of items. Often it is used to allocate a string or array whose length or upper bound is not known at run time, for example the following allocates a string of length 1024.
DECLARE size FIXED BINARY;
DECLARE string CHARACTER(size) BASED(p);
size = 1024;
ALLOCATE string SET(p);
What IS surprising, however is that the "size" of the based variable can change without reallocation. Consider the following program fragment:
[1] dcl i fixed bin(31);
[2] dcl (p,q) ptr;
[3] dcl s char(i) based;
[4] i = 8;
[5] allocate s set(p);
[6] put skip list('size of p->s ' || trim(storage(p->s)) );
[7] i = 4;
[8] allocate s set(q);
[9] put skip list('size of q->s ' || trim(storage(q->s)) );
[10] put skip list('size of p->s ' || trim(storage(p->s)) );
As expected, line 5 allocates a string of length 8, line 6 prints
"size of p->s 8"
Line 8 allocates a second string of length 4, line 9 prints
"size of q->s 4"
There are now two strings of different lengths allocated. However, line 10 prints
"size of p->s 4"
Now add the following lines:
[11] i = 16;
[12] put skip list('size of q->s ' || trim(storage(q->s)) );
What is the size of the area printed? No additional allocations have taken place.
The value is "size of q->s 16"!
This isn't quite as much of a problem if the string length is shortened, but if it's lengthened all kinds of bad can result.
For adjustable based data, the lengths and bounds expressions from the declaration are re-evaluated each time the variable is referenced. Who knew? Actually, the Multics PL/I language reference makes this clear, but the various IBM manuals seem to gloss over it.
No comments:
Post a Comment