detachment

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

detachment

Eric Winger-4
No, this isn't a question about my relationship with reality...


....param: ppErrors (lpvoid)

errorBuffer := COMTaskMemory new: itemCount * HRESULT byteSize.
errors := StructureArray fromAddress: errorBuffer length: itemCount
elementClass: HRESULT.

The above code was implemented in a COMImplementaiton object. Then the
idea was to pass back the StructureArray in a parameter.

However doing this:

ppErrors value: errors detach

results in occasionaly walkbacks at unexplained times where the Dolphin
image will lock up and give "unable to read" errors. It appears to be a
finalization problem.

Whereas:

ppErrors value: errorBuffer detach

does not *seem* to cause this problem.

In looking at the different detach methods, they appear to try to do the
same thing (obviously in diffent ways).

Should I expect this? As I thought that detaching either errors or
errorBuffer would result in the same thing.

Eric


Reply | Threaded
Open this post in threaded view
|

Re: detachment

Ian Bartholomew-5
Eric,

> ....param: ppErrors (lpvoid)
>
> errorBuffer := COMTaskMemory new: itemCount * HRESULT byteSize.
> errors := StructureArray fromAddress: errorBuffer length: itemCount
> elementClass: HRESULT.
>
> The above code was implemented in a COMImplementaiton object. Then the
> idea was to pass back the StructureArray in a parameter.

Where is errorBuffer defined?. If it is as a local variable within the
method then that might be the problem.  When the method ends, and you return
the errors object, there are no references left to the errorBuffer object so
the grabage collector reclaims it. This leaves the memory at the address
that errors is pointing at free for reuse.  In order to prevent garbage
collection you have to maintain a reference to the actual Smalltalk object
and not just a reference to the address of the object.

As a *temporary* fix, use a Global to hold the buffer and see if the problem
goes away.  NB If the method is called more than once then this won't work
as the second call will cause the reference to buffer created by the first
to be lost and garbaged

(Smalltalk at: #MyErrorBuffer) put: (COMTaskMemory new: itemCount * HRESULT
byteSize).
errors := StructureArray fromAddress: (Smalltalk at: #MyErrorBuffer) length:
itemCount elementClass: HRESULT.

A better way might be to use an instance variable but that depends a lot on
the class the above is implemented in.  However, if #detach'ing the error
buffer does work then maybe (i.e. out of my depth here!) this maintains a
reference to the COMTaskMemory (or it's underlying collection) for you that
prevents the memory being reused and is the way to go?

> Should I expect this? As I thought that detaching either errors or
> errorBuffer would result in the same thing.

I don't really know, the above is based on similar problems I had when using
the "normal" windows structures. Probably worth a look at though?

Ian


Reply | Threaded
Open this post in threaded view
|

Re: detachment

Blair McGlashan
In reply to this post by Eric Winger-4
Eric

You wrote in message news:[hidden email]...

> No, this isn't a question about my relationship with reality...
>
>
> ....param: ppErrors (lpvoid)
>
> errorBuffer := COMTaskMemory new: itemCount * HRESULT byteSize.
> errors := StructureArray fromAddress: errorBuffer length: itemCount
> elementClass: HRESULT.
>
> The above code was implemented in a COMImplementaiton object. Then the
> idea was to pass back the StructureArray in a parameter.
>
> However doing this:
>
> ppErrors value: errors detach
>
> results in occasionaly walkbacks at unexplained times where the Dolphin
> image will lock up and give "unable to read" errors. It appears to be a
> finalization problem.
>
> Whereas:
>
> ppErrors value: errorBuffer detach
>
> does not *seem* to cause this problem.
>
> In looking at the different detach methods, they appear to try to do the
> same thing (obviously in diffent ways).
>
> Should I expect this?

Yes.

>...As I thought that detaching either errors or
> errorBuffer would result in the same thing.

No. The StructureArray does not own the memory block you've associated with
it using #fromAddress:etc, it is merely a reference to it, and therefore it
doesn't modify the pointer object in any way when you detach it. In this
case the pointer is a finalizable object which will delete the associated
COM task memory heap block when it is GC'd, unless you explicitly detach it.
In other words the memory was allocated by COMTaskMemory class>>new:, and is
owned by the COMTaskMemory instance, not by the StructureArray. Therefore to
prevent the memory evaporating at an inconvenient time, you must detach the
COMTaskMemory pointer, not the StructureArray.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: detachment

Bill Schwab-2
Hi Blair,

> No. The StructureArray does not own the memory block you've associated
with
> it using #fromAddress:etc, it is merely a reference to it, and therefore
it
> doesn't modify the pointer object in any way when you detach it. In this
> case the pointer is a finalizable object which will delete the associated
> COM task memory heap block when it is GC'd, unless you explicitly detach
it.
> In other words the memory was allocated by COMTaskMemory class>>new:, and
is
> owned by the COMTaskMemory instance, not by the StructureArray. Therefore
to
> prevent the memory evaporating at an inconvenient time, you must detach
the
> COMTaskMemory pointer, not the StructureArray.

I found the copy vs. reference behavior of the various external memory
classes to be somewhat unclear, in that I was frequently uncertain of which
of the two was going to happen with any particular message.  Most of the
external interfacing that I do now allocates memory in Dolphin and passes a
pointer to a DLL to run various tight loops in C/C++; that typcially just
works.  Hooking Dolphin objects to externally allocated memory is a little
trickier.  In fairness, I haven't looked at it much (haven't needed to)
since I stopped using DCOM.  I was never sure whether the missing element is
more explicit comments in the image or a cookbook in the EducationCentre or
on the Wiki.

Looking over

  http://www.object-arts.com/wiki/html/Dolphin/ExternalInterfacing.htm

it's obvious that (surprise<g>) I never got around to writing the recipe
part of it.  My advice to the Wiki editors of the world would be to keep the
"interview" section, and, add a cookbook section that lists problems and
their solution.  If the cookbook idea isn't appropriate or easy to do, maybe
a table to cross-reference copying vs. not with types of memory and/or
contents???

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: detachment

Eric Winger-4
In reply to this post by Blair McGlashan
Blair McGlashan wrote:

>
>
> No. The StructureArray does not own the memory block you've associated with
> it using #fromAddress:etc, it is merely a reference to it, and therefore it
> doesn't modify the pointer object in any way when you detach it. In this
> case the pointer is a finalizable object which will delete the associated
> COM task memory heap block when it is GC'd, unless you explicitly detach it.
> In other words the memory was allocated by COMTaskMemory class>>new:, and is
> owned by the COMTaskMemory instance, not by the StructureArray. Therefore to
> prevent the memory evaporating at an inconvenient time, you must detach the
> COMTaskMemory pointer, not the StructureArray.
>
>

If I understand correctly, it becomes vitally important when using
external structures, that one detach the appropriate memory object, not
any "users" of said memory.

It's almost as if the ExternalStructure in this example could be
considered a view on a memory model. And that view has a lifetime of its
own independent of its underlying model.

Thanks for the responses guys.

Eric