After using a struct from PInvoke, do I need to free memory?
I need to do something like this:
TEXTMETRIC tm;
bool isTrueType = false;
if (NativeMethods.GetTextMetrics(hDC, out tm))
{
isTrueType = ((PitchAndFamily)tm.tmPitchAndFamily & PitchAndFamily.TMPF_TRUETYPE) == PitchAndFamily.TMPF_TRUETYPE;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf<TEXTMETRIC>(tm));
Marshal.StructureToPtr<TEXTMETRIC>(tm, ptr, true);
Marshal.FreeHGlobal(ptr);
}
or will the cleared memory be automatically cleared after the function exits? I think (from what I've read) this is the last one, but I'm not sure!
Any clarification was appreciated!
source to share
Marshal.StructureToPtr<TEXTMETRIC>(tm, ptr, true);
Using true is very wrong here. The memory you allocated with AllocHGlobal () is not initialized and contains random bytes. It does not contain a previous version of the struct, which must be released before the method overwrites it.
This can lead to very difficult diagnostics of random failures, depending on the values of the random bytes. You left with it because TEXTMETRIC contains no members to clean up. Calling FreeHGlobal () is sufficient, there is no need for Marshal.DestroyStructure (), you have to put it in a finally block to be exception safe. Which answers your question.
To complete, cleanup is required only if the structure contains a BSTR, SAFEARRAY, or COM interface pointer. Resources that have explicit release calls and require the [MarshalAs] attribute in the structure declaration. This is extremely rare when using pinvoke. Not uncommon when using COM interop, also uses StructureToPtr () under the hood, but the CLR does the call automatically.
source to share
The function you are calling GetTextMetrics
expects the caller to allocate and free memory for the structure. If you allocate AllocHGlobal
, you must release it with FreeHGlobal
.
However, none of this is necessary. You highlight the structure when you declare tm
. Nothing else is needed there. Avoid having to call FreeHGlobal
without calling AllocHGlobal
.
TEXTMETRIC tm;
bool isTrueType = false;
if (NativeMethods.GetTextMetrics(hDC, out tm))
{
isTrueType = ((PitchAndFamily)tm.tmPitchAndFamily & PitchAndFamily.TMPF_TRUETYPE) == PitchAndFamily.TMPF_TRUETYPE;
}
By avoiding manual allocation, you also avoid making a broken call, or even any call to StructureToPtr
that other answers are talking about.
source to share
No, if you allocate memory with AllocHGlobal
, you must free it yourself. otherwise, a memory leak will occur.
Here is the relevant part of the documentation
Pointer to newly allocated memory. This memory must be released using the Marshal.FreeHGlobal method.
source to share