【问题标题】:Memory usage from C# apps using C++ DLLs使用 C++ DLL 的 C# 应用程序的内存使用情况
【发布时间】:2021-08-26 03:23:31
【问题描述】:

为了正确起见,如果我对 C# 程序以委托作为参数调用 C++ dll 之间的数据流的想象正确,我想听听你的意见。

  1. 系统为 C# 程序提供内存
  2. C# 程序加载 .dll 并将其部分空间分配给 C++ dll。在这个空间中不会有 C# 垃圾收集,只有在卸载 .dll 之后才能释放整个空间。
  3. 调用了 C++ 函数。特定的 Function 有一个委托作为参数。我们深入 C++ 内存区域并声明一些变量。 C++ 函数将在其代码中的某处调用 C# 委托。
  4. C# 委托在 C# 内存上运行,如果输入参数是本机类型,则 C# 委托将在 C# 内存中保存一份副本,或者如果它是复杂类型,则引用 C++ 内存中的变量。如果我们有本机类型,我可以将其保存到 C# 世界中,一切都会好起来的。但是,如果它是一个引用并且我只是将它保存到我的 C# 内存中,如果我结束我的 C++ 函数,我将得到未定义的行为,因为变量将超出范围并被销毁。
  5. C#函数结束,我们得到C++中的返回值作为副本(或者返回值的指针,如果是复杂类型,指针将指向C#内存)
  6. C++函数结束,C++函数使用的内存被释放

我说得对吗?

【问题讨论】:

  • 每个问题一个个问题。

标签: c# c++ memory-management dll


【解决方案1】:

这应该在marshaller的文档中描述

如果它们是本机类型或对 C++ 内存中变量的引用,如果它是复杂类型。如果我们有本机类型,我可以将其保存到 C# 世界中,一切都会好起来的。但是如果它是一个引用并且我只是将它保存到我的 C# 内存中,如果我结束我的 C++ 函数,我将得到未定义的行为,因为变量将超出范围并被销毁

我的理解是编组器要么将复杂类型转换为结构,要么将指针 (IntPtr)。结构是按值传递的,因此您将在托管内存中拥有一个副本(可能在堆栈上)。指针需要不安全的代码才能访问,因此您将负责安全地处理它们。

C++作为拷贝(或者返回值的指针,如果是复杂类型,指针会指向C#内存)

托管函数实际上无法以安全的方式返回指向托管内存的指针。要创建指针,您需要修复对象以防止 GC 移动它,但修复是有范围的,因此它不适用于返回值。

我个人认为编组规则有点复杂,我宁愿保持任何 p/Invoke 简单,如果没有其他原因,只是为了避免有关安全的问题。对于 c# 和 c++ 之间更复杂的互操作性,我建议使用 c++/cli。这允许您自己进行类型转换,并添加一整套可用于确保正确运行的工具。

【讨论】:

  • 谢谢你,因为你没有提到我的想法中的错误,我认为哪个部分控制了哪个记忆,我猜对了。关于 marshaller 的文档对我帮助很大,我没有考虑 GC 来移动部件。你给了我很大的投入,让我进一步工作
猜你喜欢
  • 1970-01-01
  • 2013-05-11
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2017-06-03
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多