Hopefully this simple example will explain the behavior.
I have a method in a class that returns a memptr of data. The memptr is properly set to the size of my data each time.
However, if I attempt to set-size = 0, the memptr retains the size from the previous call yet get-pointer-value = 0. The only way to truly set the size to 0, is to first do a set-size() = 1!
Has anyone seen this before?
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/MemptrTest.cls:550:0]
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/MemptrTestCaller.p:550:0]
Hopefully this simple example will explain the
behavior.
I have a method in a class that returns a memptr of
data. The memptr is properly set to the size of my
data each time.
However, if I attempt to set-size = 0, the memptr
retains the size from the previous call yet
get-pointer-value = 0. The only way to truly set the
size to 0, is to first do a set-size() = 1!
Has anyone seen this before?
You need to return a MEMPTR as a parameter - they don't get cleaned up automatically when they're a return value (this is true of functions, so I'd expect it to be true of methods too).
-- peter
Are you sure the MEMPTR data is being copied from the method to the calling program?
IIRC, using function / method calls to pass newly-allocated memptrs around have some strange issues with them that make doing this problematic.
Hi Peter.
Interesting.
In my real-world application, it seems to clean-up ok. It's when I try to clean it up, by using set-size() = 0 that it doesn't clean up.
In real life, this method is inside a singleton that is returning requested data in a memptr. The odd thing is, is that it reuses the same get-pointer-value with every call. Does that make sense?
Good question Tim.
It appears to be as the data I expect to be in the memptr is there by the time it gets out to the main called procedure.
if you display a get-pointer-value on the memptr before the method return, and on the calling procedure's memptr after the return, do they point to the same location?
Hi Peter.
Interesting.
In my real-world application, it seems to clean-up
ok. It's when I try to clean it up, by using
Are you sure of this? If you use the debugger (in OEA or otherwise) you can track the life of MEMPTRs using the dynamic object monitoring functionality.
set-size() = 0 that it doesn't clean up.
In real life, this method is inside a singleton that
is returning requested data in a memptr. The odd
thing is, is that it reuses the same
get-pointer-value with every call. Does that make
sense?
In the sake of full disclosure, my experience on this comes from demo-ware :); I saw this behaviour in the attached file I was using for a demo.
-- peter
Tim, I was just checking that. Yes, they do.
Every iteration uses the same memory location. Is that expected?
Sooo.. in everyone's expert opinion, what is the "correct" way to get data in a memptr from a method?
1. Return from method:
define var m as memptr.
m = myClass:getData().
2. Return as output parameter:
define var m as memtpr.
myClass:getData(output m).
3. Pass memptr to method :
define var m as memptr
myClass:getData(m).
Thanks.
Honestly, I think this is sufficiently weird and un-documented as to warrant a call to PSC TS.
Tim
(who wishes there was a way to pass pointers around so they could be played with directly as opposed to this confusing "did it pass a pointer, or make a new memory area" thing we've got now)
Sooo.. in everyone's expert opinion, what is the
"correct" way to get data in a memptr from a method?
1. Return from method:
define var m as memptr.
m = myClass:getData().
2. Return as output parameter:
define var m as memtpr.
myClass:getData(output m).
3. Pass memptr to method :
define var m as memptr
myClass:getData(m).
I would not do #1. I also agree with Tim's comment re. TS.
-- peter
Ok, I'll send something to tech support. In the meantime, I will change my code to use an output parameter.
"You need to return a MEMPTR as a parameter - they don't get cleaned up automatically when they're a return value (this is true of functions, so I'd expect it to be true of methods too)."
Peter, can you comment on this further. Under what conditions would a memptr ever get "automatically" cleaned up? Why would this happen when used as an output parameter and what is the cleanup that is occurring?
Sorry if these are boneheaded questions, but I don't want leakage.
Peter, can you comment on this further. Under what
conditions would a memptr ever get "automatically"
cleaned up? Why would this happen when used as an
output parameter and what is the cleanup that is
occurring?
In some circumstances, if you return a handle (a ProDataSet, say) from a function, you can delete the handle before returning it, and the ABL will defer the deletion until control passes back to the caller.
This doesn't happen with memptrs (for right or wrong; your TS call may help clear that up), and so we have a leak. Output params, on the other hand, are - at least for memptrs - a shallow copy and so don't leak.
hth
-- peter
Looks like Jeff found himself a bug:
P142118: "4GL/ABL: SET-SIZE() = 0 fails to set the size of a MEMPTR variable to zero in a class METHOD."
Cause: Bug# OE00181699