Free unmanaged memory issue

  • Thread starter Thread starter benjo
  • Start date Start date
B

benjo

I'm developing a C# application that uses an ANSI C dll. I have to use
Marshal class to correctly call that function but i cannot understand
how to use those methods DestroyStructure() and FreeCoTaskMem().
Reading MSDN they seem to be different but in fact i make some
mistakes because after some hours i get an outofmemory exception.

If needed I can post my class structure to explain more deeply how my
application works

Thanks a lot


benjo
 
I'm developing a C# application that uses an ANSI C dll. I have to use
Marshal class to correctly call that function but i cannot understand
how to use those methods DestroyStructure() and FreeCoTaskMem().
Reading MSDN they seem to be different but in fact i make some
mistakes because after some hours i get an outofmemory exception.

DestroyStructure should almost never be called.

FreeCoTaskMem should be called if the DLL returns memory to you that
was allocated with CoTaskMemAlloc or similar API.

If needed I can post my class structure to explain more deeply how my
application works

Please do, and be specific about who allocates memory and who is
responsible for freeing it, and using which allocator API.


Mattias
 
Thank you for your answer, I'll be more specific:

my C# application allocates memory using Marshal.AllocCoTaskMem(),
then fill the unmanaged memory just allocated with
Marshal.StructureToPtr() for class or Marshal.Copy() for arrays.
I allocate also unmanaged memory for the return values and only
when all data is copied to the new memory I call the C library. After
the call some return values are written by C library in the unmanaged
memory block, then this memory is copied back into C# managed
structure (Marshal.PtrToStructure())

In fact C# allocates and frees memory, whereas the C library just make
some processing and writes values in that memory that C# has prepared
few lines above the function.

DestroyStructure should almost never be called.

FreeCoTaskMem should be called if the DLL returns memory to you that
was allocated with CoTaskMemAlloc or similar API.
Please do, and be specific about who allocates memory and who is
responsible for freeing it, and using which allocator API.

Code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class myClassA
{
public Int32 n_elem;

public IntPtr temperature = IntPtr.Zero;

public IntPtr length = IntPtr.Zero;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class myClassB
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] identifier = new char[8];

public Double weight = 0F;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Double[] coeffs = new Double[3];
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public myClassC
{
public IntPtr ptrClassA;

public IntPtr ptrClassB;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class myClassOut
{
public Int32 iteration;

public Single avgTemp;
}

Code:
myClassA classAObject = new myClassA();
myClassB classBObject = new myClassB();
myClassC classCObject = new myClassC();

myClassOut classOutObject = new myClassOut();

classAObject.n_elem = rowsCount;//it is the rows number returning from
a  SELECT in ORACLE
Double[] temp = new Double[rowsCount];
Double[] len = new Double[rowsCount];
//loop filling temp and len with query results
{...}

classAObject.temperature = ConvertEx.ArrayToPtr(temp) ;
classAObject.length = ConvertEx.ArrayToPtr(len);

classCObject.ptrClassA = ConvertEx.StructToPtr(classAObject );
classCObject.ptrClassB = ConvertEx.StructToPtr(classBObject );

IntPtr ptrIn = ConvertEx.StructToPtr(classCObject);
IntPtr ptrOut = ConvertEx.StructToPtr(classOutObject);

CLibrary(ptrIn,ptrOut);

Marshal.PtrToStructure(ptrOut,classOutObject);

{some processing}

{
release memory --> Now i call FreeCoTaskMem()
but from same MSDN example i understand that I should call also
DestroyStructure on object like ClassCObject and after FreeCoTaskMem
on the IntPtr variable
}

The application cyclically (every 3 seconds) performs a calculation
using the C library, the communication between C# and C is ok because
the library calculates correctly and I verify the value in memory and
in some log file that C library writes and they are always correct, my
really trouble is on memory occupation, after some hours (about a
night) of execution the occupation of C# application is huge (about
1GB).

benjo
 
In fact C# allocates and frees memory, whereas the C library just make
some processing and writes values in that memory that C# has prepared
few lines above the function.

Great, that makes things pretty easy. Just match each AllocCoTaskMem
call with a corresponding FreeCoTaskMem and you should be good.

but from same MSDN example i understand that I should call also
DestroyStructure on object like ClassCObject and after FreeCoTaskMem
on the IntPtr variable

Which example says you should call DestroyStructure?

Note that the docs for that method says it "Frees all substructures
pointed to by the specified unmanaged memory block". Substructures
include object pointers that the CLR knows about from the structure
type. In your case, all data is inline in the structures and all
pointers are in the form of IntPtrs, that the CLR can't do anything
about. So there's no need for you to call DestroyStructure.


Mattias
 
Wow the darkness is dissolving... Maybe my misunderstood is due to a
uncorrect reading (my english isn't really good) of this msdn guide
OutArrayOfStructs Sample
Great, that makes things pretty easy. Just match each AllocCoTaskMem
call with a corresponding FreeCoTaskMem and you should be good.
Which example says you should call DestroyStructure?

This is the link that let me think i should use also DestroyStructure
http://msdn2.microsoft.com/en-us/library/2k1k68kw(vs.80).aspx
Note that the docs for that method says it "Frees all substructures
pointed to by the specified unmanaged memory block". Substructures
include object pointers that the CLR knows about from the structure
type. In your case, all data is inline in the structures and all
pointers are in the form of IntPtrs, that the CLR can't do anything
about. So there's no need for you to call DestroyStructure.

Mattias

If I correctly understand your hints, and reading again the example
from msdn, could correct me if I'm saying something wrong? For example
in case i have an array of myClassC or myClassA i should call
DestroyStructure on each memory block (eache element) of the array and
after that call only once FreeCoTaskMem on the IntPtr variable which
point the whole array.
Anyway could you post me an example when I have to use
DestroyStructure?

thank you

benjo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top