Unfortunatley I don't have a solution to the OPs problem, but I have a
similar problem and have done some troubleshooting on it. I'm in way over my
head here so please don't flame me if I state the obvious.
I have written a very small test program.
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace leakapp {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal class DataContainer {
public Int32 m_arrayBindIndex = 12;
}
class Program {
static void Main(string[] args) {
Console.WriteLine("Begin...");
Console.ReadLine();
DataContainer ctx = new DataContainer();
long count = 100000;
for (long q = 0; q < 5; q++) {
for (long i = 0; i < count; i++) {
LeakClass(ref ctx);
}
Console.WriteLine("Outer: " + q.ToString());
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
Console.WriteLine("Done");
Console.ReadLine();
}
/// <summary>
/// Call the dumy dll with a reference to the DataContainer.
/// </summary>
[DllImport("foo.dll", EntryPoint = "LeakClass", CallingConvention =
CallingConvention.Cdecl)]
public static extern int LeakClass(ref DataContainer cl);
}
}
foo.h:
typedef struct _DataContainer {
int m_arrayBindIndex;
} DataContainer;
extern "C" {
// Declaration of the compression method
__declspec(dllexport) void LeakClass(DataContainer **flum);
};
foo.cpp:
// This is the main DLL file.
#include <objbase.h>
#include "foo.h"
void LeakClass(DataContainer ** flum) {
}
(Don't comment on the usefullness of the code, it is only an example, as is
probably obvious from the naming etc. :-))
Running the program and attaching DebugDiag will reveal that on every call
to the unmanaged method there is a leak of 4 bytes. The leak will be on the
default process heap due to a call to CoTaskMemAlloc (used by the
interop-marshaler). DebugDiag reports that the allocations come from
mscorwks!BlittablePtrMarshalerBase::ConvertSpaceCL RToNative+23 . I can even
remove the only field in the class DataContainer passed to the unmanaged
method, this will result in a leak of 1 byte per call. The leak is not in
managed memory, but just to avoid all replys about "The GC hasn't run yet.."
etc. I included the GC.Collect()-sequence.
The above problem arises in our production servers. These small memory leaks
will fragment the default process heap (CoTaskMemAlloc heap) eventualy
crashing the app.
So, am I doing something stupid here? I have read about pinvoke and interop
marshaling but I can't find anything that is wrong with the code. Changing
the managed definition to a struct solves the problem. I would still like to
know what is wrong with the code I posted above.
Hope someone has some insight into thi.
/Erik
"Peter Duniho" wrote:
On Tue, 24 Jun 2008 01:40:00 -0700, Victor
<Vi****@discussions.microsoft.comwrote:
Could you tell me why we should use 'out' keyword instead of 'ref'
keyword?
To the extent that your rising memory footprint is related to the
allocation of a BITMAPINFOHEADER object before calling the
VfwDecoder_GetOutputBitmapInfoHeader() function, using an "out" parameter
instead of "ref" allows you to avoid allocating the object, since it
wouldn't need to be initialized before passing to the function.
That said, I'm not really clear on the code example. The DllImport you
show is for VfwDecoder_DecompressNative, not
VfwDecoder_GetOutputBitmapInfoHeader, and you don't show us how you've
actually declared BITMAPINFOHEADER in C#. I'm relatively inexperienced
with p/invoke, so maybe it wouldn't help me understand your question
better anyway. But it could be useful to someone else with more
experience with respect to identifying anything about your code that might
be an issue.
All that said, the real bottom line here is that as long as you're dealing
with managed references to objects, the fact that your memory usage climbs
is not really a problem. The framework manages its use of actual
allocated memory from the OS independent of your own use of managed
memory, and it's not uncommon to see the process memory allocations be
larger than your application's actual use of managed memory.
Pete