RPG programmers who use RPG’s memory management operations (%ALLOC, %REALLOC and DEALLOC) should read the blog Debug Heap-Usage Problems about the debug memory manager. The debug memory manager can be used to locate errors in an application that uses heap storage. Debugging problems related to memory management can be very difficult because the symptom of the problem often occurs long after the problem was caused. I can attest from personal experience that the debug memory manager is a great tool. On one occasion it pinpointed my problem instantly. Without the debug memory manager, I would’ve had many repeated debug sessions, gradually working my way back to the original coding error that was causing the problem.
Unfortunately, by default, RPG programmers can’t take advantage of the debug memory manager. RPG’s memory-management operations use a different interface to heap storage than the one controlling whether the debug memory manager should be used. RPG uses the CEEGTST, CEECZST, and CEEFRST APIs to handle memory-management operations in 6.1, and by default in 7.1.
The good news is it’s possible for RPG programmers to take advantage of the debug memory manager by changing their RPG code. The change is simple in 7.1, and slightly more complex prior to 7.1.
In 7.1, RPG programmers can add keyword ALLOC(*TERASPACE) to the H spec of modules that use memory-management operations. Using that keyword will have two benefits. First, it will cause RPG to use the heap storage interfaces that have the option of using the debug memory manager. And second, it will allow RPG programmers to allocate much larger sizes of heap storage (up to 4,294,967,295 bytes versus the default maximum of 16,776,704 bytes).
Prior to 7.1, RPG programmers must call APIs instead of using RPG’s native memory-management operations. Instead of %ALLOC, call the _C_TS_malloc API. Instead of %REALLOC, call the _C_TS_realloc API. Instead of DEALLOC, call the _C_TS_free API.
Below is an example that uses these APIs:
D C_TS_malloc PR * EXTPROC('_C_TS_malloc')
D length 10u 0 VALUE
D C_TS_realloc PR * EXTPROC('_C_TS_realloc')
D oldPointer * VALUE
D newLength 10u 0 VALUE
D C_TS_free PR EXTPROC('_C_TS_free')
D pointer * VALUE
D p S *
D array S 10A DIM(10) BASED(p)
D numElems S 10I 0
// Allocate storage for 2 elements of the array
numElems = 2;
p = C_TS_malloc(%size(array) * numElems);
array(1) = 'one';
array(2) = 'two';
// Increase to 3 elements
numElems = 3;
p = C_TS_realloc(p : %size(array) * numElems);
array(3) = 'three';
dsply (array(1) + array(2) + array(3));
// Free the array
p = *NULL;
For more information about the ALLOC keyword, go here.
For more information about the memory management APIs, see the information for malloc(), realloc() and free().
This blog was guest-written by Barbara Morris. Barbara is the lead developer for the RPG compiler in the IBM Toronto Lab. She has been working on the RPG compilers since she started at IBM in 1989 after receiving a Computing Science degree from the University of Alberta. Her first RPG enhancements for RPG/400 were ENDDO/ENDIF and *ON/*OFF. Her latest enhancement for ILE RPG is Open Access: RPG Edition. Thanks, Barbara!
This blog post was originally published on IBMSystemsMag.com and is reproduced here by permission of IBM Systems Media.