I could probably do an Ask Reuben article on this topic. From the days of my first Genero migration many years ago now, something along the lines of what Rene said "The memory has been allocated with malloc(). Memory allocated by malloc is owned by the process forever." is what I recall.
Having done an aggressive transformation of static arrays to dynamic arrays, and chars to strings, we felt we were ahead. However it was still prudent to put a cap on QBEs for report/enquiry programs, and similarly a limit on records in a zoom window etc so that a user did not select all records (1000+) from a table and eat up some memory that would be retained for the life of a program. Also taking into account the expected lifetime of a program, most programs had lifetime of less than 5 minutes so not too big a problem if it has excessive memory use due to user input, but for the programs that ran all day e.g. menu, pos programs, a bit more important that an unchecked QBE does not end up holding memory unnecessarily all day.
One thing I am curious that I have never got round to looking at is whether in the case of a sparse array, are dictionaries better than dynamic array e.g.
MAIN
TYPE y_type DICTIONARY OF INTEGER
TYPE xy_type DICTIONARY OF y_type
DEFINE xy_value xy_type
LET xy_value[100000][50000] = 100
DISPLAY xy_value[100000][50000]
END MAIN
... so if you were worried about memory consumption of a dynamic array with dimension 2, is something like that better? at the cost of losing some array functionality.