[英]How to get IntPtr of c# unsafe struct to free its memory initialized in c++ dll
Please, advise me on how to free memory from the created unsafe
C# struct
(s) using some standard C# toolset or how get I get the IntPtr
of those objects to use the default provided custom C++ library?请告诉我如何使用一些标准 C# 工具集从创建的
unsafe
C# struct
中释放内存,或者如何让这些对象的IntPtr
使用默认提供的自定义 C++ 库?
The problem details (UPD):问题详细信息(UPD):
I create the C# unsafe struct
and pass it to C++ dll that I can't change TH_ExtractBimTemplate(ref createdStruct)
.我创建了 C#
unsafe struct
并将其传递给我无法更改的 C++ dll TH_ExtractBimTemplate(ref createdStruct)
。 The dll updates its content. dll 更新其内容。 And in addition to that, the dll saves the reference to the struct object inside of it in an internal list.
除此之外,dll 将对其内部结构对象的引用保存在内部列表中。 Here is the struct definition:
这是结构定义:
public unsafe struct BIM_Template { public ushort ImageSizeX; public ushort ImageSizeY; public fixed uint Mint[MAX_MINUTIAE_SIZE]; public uint Reserve; }
After the API call returns, I use the data in the struct populated by the C++ dll in my C# code. API 调用返回后,我在 C# 代码中使用由 C++ dll 填充的结构中的数据。
I need to free the memory used by the struct and C++.我需要释放结构和 C++ 使用的内存。 The dll has an API to do this,
TH_FreeMemory
. dll 有一个 API 可以执行此操作,
TH_FreeMemory
。
For step #3 I need to pass the object reference (I presume IntPtr
) to C++ library or I need to Free the memory it was occupying with some C# instrument.对于第 3 步,我需要将对象引用(我假设为
IntPtr
)传递给 C++ 库,或者我需要释放它被某些 C# 工具占用的内存。
The Garbage Collection doesn't work even if there are no reference in my C# code to the object, I assume, because of the struct object reference is stored in the list in the dll that I don't control.我假设,即使我的 C# 代码中没有对该对象的引用,垃圾收集也不起作用,因为结构对象引用存储在我无法控制的 dll 的列表中。 When
TH_FreeMemory
on the struct object is called, it removes it from the list and release the memory with delete
, but I can't generate the C# IntPtr
to pass it to the TH_FreeMemory
for that...当调用结构对象上的
TH_FreeMemory
时,它会将其从列表中删除并使用delete
释放内存,但我无法生成 C# IntPtr
以将其传递给TH_FreeMemory
......
How can I do that - release the memory with just C# tools, ignoring the list dll or generate the IntPtr
for this struct?我该怎么做 - 仅使用 C# 工具释放内存,忽略列表 dll 或为此结构生成
IntPtr
?
The implementation details:实施细则:
This is how I create and initialize it:这就是我创建和初始化它的方式:
BIM_Template template = default;
var template = TH_ExtractBimTemplate(ref template)
Where TH_ExtractBimTemplate(...)
is the method that is pulled from the C++ dll in this way:其中
TH_ExtractBimTemplate(...)
是以这种方式从 C++ dll 中提取的方法:
[DllImport("TemplateHelper.dll")]
private static extern int TH_ExtractBimTemplate(
ref BIM_Template out_template);
The TemplateHelper.dll
provides me a C++ method to release the memory - TH_FreeMemory
: TemplateHelper.dll
为我提供了一种释放内存的 C++ 方法 - TH_FreeMemory
:
int WINAPI TH_FreeMemory( void *memblock, BIM_MemBlockType memblock_type )
This is how I plug it into C#这就是我将它插入 C# 的方式
[DllImport("TemplateHelper.dll")]
private static extern int TH_FreeMemory(
IntPtr memblock, BIM_MemBlockType memblock_type
);
Current solutions I tried:我尝试过的当前解决方案:
IntPtr
of the created unsafe struct
(the template variable) but I don't know how to get it, to free allocated memory with TH_FreeMemory
dll methodunsafe struct
(模板变量)的IntPtr
,但我不知道如何获取它,以使用TH_FreeMemory
dll 方法释放分配的内存unsafe struct
type templates in the method that create them and return void, leaving no references to the created templates, but the garbage collector doesn't free memory.unsafe struct
类型模板,不留下对创建模板的引用,但垃圾收集器不会释放内存。 I assume that is, because of the object type is unsafe struct
.unsafe struct
。 At least, I've waited for 40 minutes and memory wasn't released.Marshal.FreeHGlobal(IntPtr ptr)
but that doesn't reduce the amount of unmanaged memory used by the app as well here is the code:Marshal.FreeHGlobal(IntPtr ptr)
释放内存,但这并没有减少应用程序使用的非托管内存量,这里是代码:[Fact]
public void TestDisposalIsCalledOnOutOfContext()
{
// Create templates
var templates = LoadTemplates(m, Output);
// Release the allocated memory using Marshal
templates.ForEach( t => MarshaFreeMemory(ref t));
// Wait
Thread.Sleep(new TimeSpan(hours: 1, 0, 0));
}
private static IntPtr MarshaFreeMemory(ref BIM_Template? template)
{
IntPtr ptr;
ptr = Marshal.AllocHGlobal(Marshal.SizeOf<BIM_Template>());
Marshal.StructureToPtr(template, ptr, true);
Marshal.FreeHGlobal(ptr);
return ptr;
}
private static List<BIM_Template?> LoadTemplates()
{
var templates = new List<BIM_Template?>();
for (int j = 0; j < 1000; j++) templates.Add(LoadTemplate());
return templates;
}
public static BIM_Template LoadTemplate()
{
BIM_Template template = default;
var template = TH_ExtractBimTemplate(ref template);
return template;
}
So, the question is how can I prevent these memory leaks and free memory from the created templates using some standard C# toolset or how get I get the IntPtr
of the template object to use the library?因此,问题是如何使用某些标准 C# 工具集从创建的模板中防止这些内存泄漏和释放内存,或者如何让模板对象的
IntPtr
使用该库?
You don't need to call TH_FreeMemory
.您无需调用
TH_FreeMemory
。 Your structure doesn't have any pointers inside.您的结构内部没有任何指针。 In C++, the
Mint
field should be std::array<uint32_t, MAX_MINUTIAE_SIZE>
or an equivalent.在 C++ 中,
Mint
字段应该是std::array<uint32_t, MAX_MINUTIAE_SIZE>
或等效项。
Your template
local variable is on the stack, it does not use any heap memory, and the stack memory will be freed automatically just before the LoadTemplate()
method returns.您的
template
局部变量在堆栈上,它不使用任何堆内存,并且堆栈内存将在LoadTemplate()
方法返回之前自动释放。
if you wanna free the memory used by the list in TestDisposalIsCalledOnOutOfContext
, do this:如果您想释放
TestDisposalIsCalledOnOutOfContext
中列表使用的内存,请执行以下操作:
templates = null;
// Collect all generations of memory
GC.Collect();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.