MEMPTR as a parameter - pass by value or reference?

Posted by Tim Kuehn on 06-Jul-2017 13:06

I'm writing some code that'll pass memptrs around, and I need to confirm that MEMPTR are pass-by-reference and not pass-by-value.

In other words - for this code snippet: 

RUN Memptr/Callee.p(mptrTest).

Will the parameter in Callee.p reference the memory pointed to by mptrTest, or a copy of that area?

I know that 

Assign Mptr1 = Mptr2.

Creates a new memptr and copies the values from 2 to 1 - I want to make sure that passing a memptr reference to a method, procedure, or function does not do this. 

Posted by Laura Stern on 06-Jul-2017 13:50

Yes, the parameter is by reference  - different from the assignment, which makes a copy.  Try this code:

DEFINE VAR mm AS MEMPTR.

SET-SIZE(mm) = 10.

PUT-STRING(mm, 1) = "ABC".

RUN foo(mm).

MESSAGE "In caller" SKIP

       GET-STRING(mm, 1) SKIP

       GET-POINTER-VALUE(mm)

       VIEW-AS ALERT-BOX.

PROCEDURE foo:

   DEFINE INPUT PARAMETER mm2 AS MEMPTR.

   PUT-STRING(mm2, 4) = "XXX".

   MESSAGE "Inside foo" SKIP

               GET-STRING(mm2, 1) SKIP

               GET-POINTER-VALUE(mm)

               VIEW-AS ALERT-BOX.

END.

All Replies

Posted by Brian K. Maher on 06-Jul-2017 13:10

You can use get-pointer-value() to see if they are the same.

Posted by marian.edu on 06-Jul-2017 13:20

memptr it’s just a pointer, hence the name… and that’s always a reference ;)

mind you that’s ‘unmanaged’ resource and need to be freed, no garbage collector will do that for you and once you lose the reference to it you can’t get to it anymore 

Posted by Brian K. Maher on 06-Jul-2017 13:24

DynObjects.Other logging will give you create/delete info for memptr variables.

Posted by jmls on 06-Jul-2017 13:44

mmmm. memory pointers. My favourite feature in a 4GL ;)

Posted by Laura Stern on 06-Jul-2017 13:50

Yes, the parameter is by reference  - different from the assignment, which makes a copy.  Try this code:

DEFINE VAR mm AS MEMPTR.

SET-SIZE(mm) = 10.

PUT-STRING(mm, 1) = "ABC".

RUN foo(mm).

MESSAGE "In caller" SKIP

       GET-STRING(mm, 1) SKIP

       GET-POINTER-VALUE(mm)

       VIEW-AS ALERT-BOX.

PROCEDURE foo:

   DEFINE INPUT PARAMETER mm2 AS MEMPTR.

   PUT-STRING(mm2, 4) = "XXX".

   MESSAGE "Inside foo" SKIP

               GET-STRING(mm2, 1) SKIP

               GET-POINTER-VALUE(mm)

               VIEW-AS ALERT-BOX.

END.

Posted by Tim Kuehn on 06-Jul-2017 13:56

Thx Laura - I did something similar with a caller / callee procedure and the get-point-value() was the same on both sides of the call.

Being the paranoid developer I am, I wanted to make sure what I thought I was seeing was, in fact, correct, and wouldn't result in a memory leak, or information not being passed back to the caller.

Posted by gus bjorklund on 09-Jul-2017 03:29

> On Jul 6, 2017, at 2:45 PM, jmls wrote:

>

> mmmm. memory pointers. My favourite feature in a 4GL ;)

>

>

>

indeed. but we had to add it to support various interfaces to the outside world.

Posted by Peter Judge on 10-Jul-2017 09:47

Tim,

One thing that becomes important when working with MEMPTRs is that they can only have a size allocated once in the ABL. You cannot resize them dynamically (although hopefully this will be mitigated/solved soon). This is especially pertinent when working with sockets - you cannot be sure how many chunks of data you are receiving and how much data is in each chunk. Now you get into a game of copying data and and/or reallocating memory and general pain ensues.

I ran into this when writing the HTTP Client and ended up creating a wrapper about all that painful, annoying stuff. It's called a ByteBucket: documentation.progress.com/.../OpenEdge.Core.ByteBucket.html . You can just throw data into/at it and it'll do the internal resizing and allocations for you.

This thread is closed