Hi Lim,
<SOAPBOX STATE="ON">
Why do you want to dynamically allocate such a small array?
Is there a good reason why the array is being allocated in the procedure
instead of by the caller? Normally, you want storage management to be
done by the caller. The exception is when the storage management is
significantly complicated, and therefore needs to be encapsulated.
In my opinion, dynamic arrays do more harm than good. They make
programs more complicated than they need to be. They make the
programmers concentrate too much on infrastructure, and that takes away
from their ability to concentrate on the business logic.
They also require extra code to re-size and re-allocate the array, and
that code takes extra CPU time. The performance hit is usually not
significant, but why incur the extra CPU time if you don't have to?
I mean, think about it... your array is only 640k of memory. That's
barely more than half a megabyte! Your system will never notice that
memory. There's probably a thousand other things on your system that
are wasting more storage than that. Think about it: the i uses both
disk and memory in the same address space... "Single level store" they
call it. That means that every disk object you haven't cleaned up,
every spooled file you haven't cleaned up, etc, is taking up storage
just like your array is. Any one of them is probably more than 640k!
Why would you want to add the complexity of a dynamic array to save a
few kilobytes?
Also storage management inside a procedure to be passed back to it's
caller is usually a mistake. That means every time the procedure is
called, you must always reserve new storage. you can never re-use
existing storage, since the caller would have to be in control for that
to happen. It also places an onus upon the caller to make sure they
deallocate the memory, making your routines more cumbersome to use, and
requiring your caller to know more about how your routines work.
Furthermore, it requires you to pass a pointer to the procedure, which
means the compiler can't help with error checking on the parameters.
Let's say your dynamic list is a list of employees to be returned from
an employee master file. I would suggest putting THIS in the copy book
for your business logic:
D EMPLOYEE_NAME S 20a based(Template)
D EMPLOYEE_getList...
D PR 10i 0
D piKey 4a const
D piList like(EMPLOYEE_NAME)
D dim(32767) options(*varsize)
D piMax 10i 0 const
The idea is that the caller will provide an "employee list" array, and
you will populate it. (instead of you generating the array dynamically).
Since the procedure doesn't want to make any assumptions about how big
that array can be, it allows for as many as 32767 employees to be
returned. However, it also specifies options(*varsize) so the caller
can pass a smaller array if it wants to. Then, piMax is passed by the
caller to tell the procedure how many elements (at most) can be placed
in the array...
The routine then looks like this:
D EMPLOYEE_getList...
D PI 10i 0
D piKey 4a const
D piList like(EMPLOYEE_NAME)
D dim(32767) options(*varsize)
D piMax 10i 0 const
D x s 10i 0 inz(0)
/free
setll *start EMPLMAS;
read EMPLMAS;
dow not %eof(EMPLMAS);
if (x >= piMax);
// error -- out of array space.
return -1;
else;
x = x + 1;
piList(x) = EMPNAM;
endif;
read EMPLMAS;
enddo;
return x;
/end-free
P E
The code uses piMax to verify that it hasn't overflowed the array. It
simply loads the array elements, and an IF statement verifies that it
hasn't exceeded the size of the array. When all is done, it returns
the number of employee names that it found in the file, or -1 if an
error occurs.
The caller may not want 32767 names... maybe it only wants 100 at most,
so it could do the call like this:
/copy WHATEVER
D names s like(EMPLOYEE_NAME)
D dim(100)
count = EMPLOYEE_getList('key': names: %elem(names));
if (count = -1);
// handle error
endif;
No need for a dynamic array or dynamic allocation of elements... No
need for the procedure to handle all of the allocation for the caller,
or for the caller to remember to deallocate the result...
</SOAPBOX>
Okay... now that I've finished protesting :)
Why do you think your way doesn't seem safe?
Lim Hock-Chai wrote:
is there a way to safely return a dynamic array from an export procedure
to the caller? Something like below just doesn't look very safe for me.
P getListInDynaArray...
D pi
D piKey 4
D piRtnListDynaArray...
D *
D myDynaArray s 20 dim(32767) based(myDynaArray_p)
/free
myDynaAry_p = %alloc(200);
. . .
piRtnListDynaArray = myDynaArray_p
/end-free
As an Amazon Associate we earn from qualifying purchases.