R
R. MacDonald
Hello, all,
I am currently working on a .Net (VB) application that invokes routines
in unmanaged (Fortran) DLLs. The unmanaged routines then communicate
with the .Net application by means of a call-back mechanism. These
calls pass a string that contains a "command" and a pointer to a
SafeArray that (depending on the command) either receives data from the
..Net application or provides data to the .Net application.
This mechanism is working fine.
However, there might be a problem related to garbage collection. Here
is what I was trying to do:
1. Create a SafeArray in the unmanaged code.
2. Pass a pointer to the SafeArray to the .Net call-back routine for
processing.
3. After the .Net call-back is finished, the unmanaged code
"destroys" the SafeArray to free its resources.
Step 3 fails! On examination, it appeared there was no longer a
SafeArray at the original pointer location. What I discovered was that
the value of the pointer to the SafeArray was being changed by the call
to the .Net routine. There WAS a SafeArray at this changed location.
It appeared to have the same contents as the original SafeArray and,
from unmanaged code, I can "destroy" the SafeArray at this new location.
Some research at:
http://msdn.microsoft.com/library/d...ry/en-us/cpguide/html/cpconcopyingpinning.asp
revealed:
<quote>======================
Reference Types
.... Reference types have the following conditional behavior:
If a reference type is passed by value and it has members of
non-blittable types, the types are converted twice:
When an argument is passed to the unmanaged side.
On return from the call.
<end-quote>===================
Now, I'm passing the SafeArray in the opposite direction. I.e. from
unmanaged code to managed code. But if something similar applies, then
it would seem that on return I have received a different SafeArray than
the one I passed. And the one I passed seems to no longer exist!
The only immediate complication that I had from this was from a table of
allocated resources I was keeping (so that I could be sure these get
cleaned up properly before returning from the unmanaged routine). In
this table the pointers for SafeArrays that had been passed to .Net were
no longer valid (so freeing the corresponding SafeArrays failed). (I
can see that there could have been additional consequences had I wanted
to do anything more serious with the original SafeArrays.)
But my real question now is: "What happened to the original SafeArray?"
Did (or will) .Net's Garbage Collector take care of it, or have I now
got a memory leak?
Secondary questions are:
Will the .Net Garbage Collector clean-up the SafeArray that it has
created/substituted for the original? If so, how will it know that the
unmanaged code has finished with it? (The only .Net reference is in the
no-longer-active call-back routine.)
If I destroy the substituted SafeArray in unmanaged code, will this
cause some angst for the .Net Garbage Collector?
I sure wish I had a clear picture of how all this was working. Any
enlightenment (or pointers to helpful documentation) will be much
appreciated.
Cheers,
Randy
I am currently working on a .Net (VB) application that invokes routines
in unmanaged (Fortran) DLLs. The unmanaged routines then communicate
with the .Net application by means of a call-back mechanism. These
calls pass a string that contains a "command" and a pointer to a
SafeArray that (depending on the command) either receives data from the
..Net application or provides data to the .Net application.
This mechanism is working fine.
However, there might be a problem related to garbage collection. Here
is what I was trying to do:
1. Create a SafeArray in the unmanaged code.
2. Pass a pointer to the SafeArray to the .Net call-back routine for
processing.
3. After the .Net call-back is finished, the unmanaged code
"destroys" the SafeArray to free its resources.
Step 3 fails! On examination, it appeared there was no longer a
SafeArray at the original pointer location. What I discovered was that
the value of the pointer to the SafeArray was being changed by the call
to the .Net routine. There WAS a SafeArray at this changed location.
It appeared to have the same contents as the original SafeArray and,
from unmanaged code, I can "destroy" the SafeArray at this new location.
Some research at:
http://msdn.microsoft.com/library/d...ry/en-us/cpguide/html/cpconcopyingpinning.asp
revealed:
<quote>======================
Reference Types
.... Reference types have the following conditional behavior:
If a reference type is passed by value and it has members of
non-blittable types, the types are converted twice:
When an argument is passed to the unmanaged side.
On return from the call.
<end-quote>===================
Now, I'm passing the SafeArray in the opposite direction. I.e. from
unmanaged code to managed code. But if something similar applies, then
it would seem that on return I have received a different SafeArray than
the one I passed. And the one I passed seems to no longer exist!
The only immediate complication that I had from this was from a table of
allocated resources I was keeping (so that I could be sure these get
cleaned up properly before returning from the unmanaged routine). In
this table the pointers for SafeArrays that had been passed to .Net were
no longer valid (so freeing the corresponding SafeArrays failed). (I
can see that there could have been additional consequences had I wanted
to do anything more serious with the original SafeArrays.)
But my real question now is: "What happened to the original SafeArray?"
Did (or will) .Net's Garbage Collector take care of it, or have I now
got a memory leak?
Secondary questions are:
Will the .Net Garbage Collector clean-up the SafeArray that it has
created/substituted for the original? If so, how will it know that the
unmanaged code has finished with it? (The only .Net reference is in the
no-longer-active call-back routine.)
If I destroy the substituted SafeArray in unmanaged code, will this
cause some angst for the .Net Garbage Collector?
I sure wish I had a clear picture of how all this was working. Any
enlightenment (or pointers to helpful documentation) will be much
appreciated.
Cheers,
Randy