freeing MEMPTR returned by a function

granth

New Member
My understanding is that from Progress 9.1 onwards, when you pass a MEMPTR from process A to B then B is actually sent a COPY of the data (i.e. A and B now have entirely seperate MEMPTRs).

If A is a function that returns a MEMPTR B, then how do I free up the memory used by A's Memptr AFTER it has returned it to B?

B can do set-size(memptrB) = 0 on it's copy of the memptr but A cannot do this.
 
If you return the memptr as an output parameter instead of the return value, you won't have that problem. I tested with this code:

DEF VAR i AS INT NO-UNDO.
DEF VAR X AS MEMPTR NO-UNDO.


FUNCTION mPtr RETURNS INT (OUTPUT thePtr AS MEMPTR):
SET-SIZE(thePtr) = 1000.
/* here you would PUT your data... */

RETURN GET-SIZE(thePtr).
END FUNCTION.

DO i = 1 TO 100:
SET-SIZE(X) = mPtr(OUTPUT X).
SET-SIZE(X) = 0.
END.

If you check, all memory should be released.

Don't know if this is feasible for your application, but hope it helps!

--Mike
 
Thanks for the reply mbouchard but I am still not clear on this point.

Consider this code (based around your example):

DEF VAR a AS INT NO-UNDO.
DEF VAR X AS MEMPTR NO-UNDO.

FUNCTION mPtr RETURNS MEMPTR (INPUT cString AS CHAR):

DEF VAR Y AS MEMPTR NO-UNDO.
MESSAGE "Y:" GET-SIZE(Y) VIEW-AS ALERT-BOX.
SET-SIZE(Y) = 0.
SET-SIZE(Y) = LENGTH(cString).
PUT-STRING(Y,1 , LENGTH(cString)) = cString.

RETURN Y.

END FUNCTION.

DO a = 0 TO 10000:

a = MAX(1, a * 10).
X = mPtr(string(a)).
MESSAGE "X:" GET-SIZE(X) VIEW-AS ALERT-BOX.

END.

SET-SIZE(X) = 0.

You can see that it's not necessary for function MPtr to send the size back to the caller as pointer X will automatically resize on each call (this is proven by the fact that X is not reset with set-size(x) = 0 before each call to the function).

However your example and mine still do not resolve the question of how pointer Y should be 'freed up' after it is returned. Wether the function sends it back as the return value or a parameter is irrelevant as what is sent back is a COPY and not the original pointer itself.
 
I understand what you're saying - it seems that, based upon the Progress documentation, the function should be causing a memory leak because the local variable Y's memory is not being released with SET-SIZE. I tried a slight modification of your example (I put the SET-SIZE(X) = 0 statement inside the loop to release X's memory after calling the function - see below), and found that there was no memory leak. I used windowsXP's task manager to monitor the memory usage.

Perhaps a copy is made when doing a direct assignment with the = operator,
but memptr's passed as parameters are passed by reference. It's the only thing that makes sense to me...

DEF VAR a AS INT NO-UNDO.
DEF VAR X AS MEMPTR NO-UNDO.

FUNCTION mPtr RETURNS MEMPTR (INPUT cString AS CHAR):

DEF VAR Y AS MEMPTR NO-UNDO.
MESSAGE "Y:" GET-SIZE(Y) VIEW-AS ALERT-BOX.
SET-SIZE(Y) = 0.
SET-SIZE(Y) = LENGTH(cString).
PUT-STRING(Y,1 , LENGTH(cString)) = cString.

RETURN Y.

END FUNCTION.

DO a = 0 TO 10000:

a = MAX(1, a * 10).
X = mPtr(string(a)).
MESSAGE "X:" GET-SIZE(X) VIEW-AS ALERT-BOX.
SET-SIZE(X) = 0.

END.
 
I spoke to a (senior) Progress consultant about this and even he seemed less than certain about this issue. After speaking to yet another conultant he came back with the suggestion that the function have 2 purposes depending on an input parameter, which would tell the function to either create and populate a memptr or simply set it to size 0.

This seems pretty clumsy as you have to remember to call the function a 2nd time in it's 'reset' mode.

Anyway, your post has taught me something new - I've been programming in Progress for 10 years now and never knew that functions can return OUTPUT parameters. Is this a recent addition to the 4GL??? I'll be posting a question about this now.
 
Back
Top