使用 C++ DLL 的 C# 应用程序的内存使用情况
Memory usage from C# apps using C++ DLLs
为了正确起见,如果我对数据流在 C# 程序之间如何调用以委托作为参数的 C++ dll 的想象是正确的,我想听听您的意见。
- 系统给C#程序分配内存
- C# 程序加载 .dll 并将其中的一些 space 提供给 C++ dll。在这个 space 中不会有 C# 垃圾回收,只有卸载 .dll 然后才能释放整个 space.
- 调用了一个 C++ 函数。特定的函数有一个委托作为参数。我们深入 C++ 内存区域并声明一些变量。 C++ 函数将在其代码中的某处调用 C# 委托。
- C# 委托在 C# 内存上运行,如果它们是本机类型,则将在 C# 内存中拥有其输入参数的副本;如果是复杂类型,则 C# 委托将拥有对 C++ 内存中变量的引用。如果我们有本地类型,我可以将它保存到 C# 世界中,一切都会好起来的。但是如果它是一个引用并且我只是将它保存到我的 C# 内存中,如果我结束我的 C++ 函数,我将得到未定义的行为,因为变量将超出范围并被销毁。
- C#函数结束,我们得到C++中的返回值作为副本(或者指向返回值的指针,如果是复杂类型,指针会指向C#内存)
- C++函数结束,释放C++函数占用的内存
我说的对吗?
这应该在 marshaller
的文档中描述
if they are native types or a reference to the variables in the C++ memory, if it is a complex type. If we have native types I can just save it into the C# world and all will be fine. But if it is a reference and I just save it into my C# memory, I will get undefined behavior, if I end my C++ function, because the variables will get out of scope and will be destroyed
我的理解是编组器会将复杂类型转换为结构或指针 (IntPtr)。结构按值传递,因此您将在托管内存中(可能在堆栈上)有一个副本。指针需要不安全的代码才能访问,因此您将负责安全地处理它们。
C++ as copy (or a pointer to the returnvalue, if it is a complex type, the pointer will point into the C# memory)
托管函数实际上没有办法以安全的方式 return 指向托管内存的指针。要创建指针,您需要修复对象以防止 GC 移动它,但修复是有范围的,因此它不适用于 return 值。
我个人认为编组规则有点复杂,我宁愿保持任何 p/Invoke 简单,除非是为了避免安全问题。对于 c# 和 c++ 之间更复杂的互操作性,我建议使用 c++/cli。这允许您自己进行类型转换,并添加了一整套可用于确保正确运行的工具。
为了正确起见,如果我对数据流在 C# 程序之间如何调用以委托作为参数的 C++ dll 的想象是正确的,我想听听您的意见。
- 系统给C#程序分配内存
- C# 程序加载 .dll 并将其中的一些 space 提供给 C++ dll。在这个 space 中不会有 C# 垃圾回收,只有卸载 .dll 然后才能释放整个 space.
- 调用了一个 C++ 函数。特定的函数有一个委托作为参数。我们深入 C++ 内存区域并声明一些变量。 C++ 函数将在其代码中的某处调用 C# 委托。
- C# 委托在 C# 内存上运行,如果它们是本机类型,则将在 C# 内存中拥有其输入参数的副本;如果是复杂类型,则 C# 委托将拥有对 C++ 内存中变量的引用。如果我们有本地类型,我可以将它保存到 C# 世界中,一切都会好起来的。但是如果它是一个引用并且我只是将它保存到我的 C# 内存中,如果我结束我的 C++ 函数,我将得到未定义的行为,因为变量将超出范围并被销毁。
- C#函数结束,我们得到C++中的返回值作为副本(或者指向返回值的指针,如果是复杂类型,指针会指向C#内存)
- C++函数结束,释放C++函数占用的内存
我说的对吗?
这应该在 marshaller
的文档中描述if they are native types or a reference to the variables in the C++ memory, if it is a complex type. If we have native types I can just save it into the C# world and all will be fine. But if it is a reference and I just save it into my C# memory, I will get undefined behavior, if I end my C++ function, because the variables will get out of scope and will be destroyed
我的理解是编组器会将复杂类型转换为结构或指针 (IntPtr)。结构按值传递,因此您将在托管内存中(可能在堆栈上)有一个副本。指针需要不安全的代码才能访问,因此您将负责安全地处理它们。
C++ as copy (or a pointer to the returnvalue, if it is a complex type, the pointer will point into the C# memory)
托管函数实际上没有办法以安全的方式 return 指向托管内存的指针。要创建指针,您需要修复对象以防止 GC 移动它,但修复是有范围的,因此它不适用于 return 值。
我个人认为编组规则有点复杂,我宁愿保持任何 p/Invoke 简单,除非是为了避免安全问题。对于 c# 和 c++ 之间更复杂的互操作性,我建议使用 c++/cli。这允许您自己进行类型转换,并添加了一整套可用于确保正确运行的工具。