CLR对非托管组件的内存管理我有点懵,也许这道题很傻。为非托管组件分配的内存在哪里?在我的.net代码中,如果我启动一个非托管组件,是否会加载该组件并分配内存?CLR如何在托管堆和非托管堆之间进行调用?编辑感谢您的回复,但我要问的是假设我制作了一个User32.Dll的DLLIMPORT,这显然是一个非托管DLL,我现在调用User32.DLL中的一些函数我的问题是,CLR如何编组我的A调用这个无人驾驶的dll?它开始很简单。pinvoke编组器首先调用LoadLibrary并通过DllImportAttribute.Value属性传递您指定的DLL名称。在您的情况下,user32.dll已经加载,因为它是由.NETbootstrap加载的,它的引用计数只是增加了。但通常Windows加载程序将DLL映射到进程的地址空间,以便调用导出的函数。接下来是GetProcAddress以获取要调用的函数的地址,即DllImportAttribute.EntryPoint属性。除非您使用ExactSpelling,否则编组器会进行多次尝试。像“foo”这样的函数名称可以用几种可能的方式进行测试,foo和fooW或fooA。与Unicode和Ansi字符之间的差异相关的烦人的Win32实现细节。CharSet属性在这里很重要。现在我需要挥动一下,因为它变得很棘手。编组器构造一个栈帧,设置需要传递给导出函数的参数。这需要低级代码,小心地排除在窥视之外。从表面上看,它执行Marshal类支持的托管类型和非托管类型之间的转换。DllImportAttribute.CallingConvention属性在这里很重要,因为它决定了需要放置哪个参数值,以便被调用的函数可以正确读取它。接下来,它设置一个SEH异常处理程序,以便可以捕获被调用代码抛出的硬件异常并将其转换为托管异常。生成更常见的一个,AccessViolationException。和别的。接下来,它将一个特殊的cookie压入堆栈,以指示非托管代码即将开始使用堆栈。这可以防止垃圾收集器浮动到非托管堆栈帧并将它在那里找到的指针解释为托管对象引用。您可以在调试器的调用堆栈[ManagedtoNativeTransition]中看到此cookie。接下来直接调用GetProcAddress()中的函数地址即可。这会导致非托管代码运行。调用后,可能需要清理以释放为传递非托管参数分配的内存。可能需要将返回值转换回托管值。就是这样,假设没有发生任何令人讨厌的事情,继续下一个托管代码语句。非托管内存分配来自进程堆。您负责分配/取消分配内存,因为它不会被垃圾收集,因为GC不知道这些对象。作为一篇学术文章对此处发布内容的扩展:CLR使用大约8个不同的堆:加载程序堆:包含CLR结构和类型系统高堆:静态、方法表、FieldDescs、接口映射低堆:EEClass、ClassLoader和查找表存根堆:CAS、COMWrapper、P/InvokeLargeObject的存根堆:需要超过85k字节的内存分配GC堆:用户分配的堆内存,专用于应用程序JIT代码堆:由mscoreee(执行引擎)内存和JIT编译器进程分配/托管代码的基本堆:互操作/非托管分配、本机内存等。HTHMichael回答了您的部分问题。我回答剩下的。如果CLR加载到非托管进程中,则称为CLR托管。这通常涉及调用mscoreeDLL中的入口点,然后加载默认的AppDomain。在这种情况下,CLR向进程请求一块内存,当给定后,它就成为它的内存空间,并且有一个栈和一个堆。以上就是C#学习教程:CLR分享非托管组件内存管理的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处:
