既然 .NET 值类型(托管 C++ 结构)存储在堆栈上,为什么需要(或者实际上)pin_ptr 它们以便将指针传递给非托管函数?
例如。字节b[100];
如果我将 &b 传递给非托管函数而不先固定它,堆栈可能会损坏吗?
CLR 堆栈是否会像 GC 堆一样发生变化?我相信 CLR 堆栈使用了不寻常的优化,例如使用处理器寄存器,这使得它不适合用作非托管函数的缓冲区。关于在堆栈上固定值类型的规则似乎不清楚。
我注意到以这种方式将缓冲区数组发送到内核 NTDLL 函数 NtfsControlFile 时似乎出现了一些损坏。固定值类型可以解决问题。但绝不会调用 API。
因此,在不首先固定它们的情况下,将指向堆栈上任何值类型的任何指针传递给任何非托管函数从根本上来说不是不安全吗?
最佳答案
您是正确的,BYTE b[100];
是在 native 堆栈上创建的,因此不受托管堆移动等的影响。但是我相信您的问题是一个简单的 C++ 错误。
你说,
If I pass &b to an unmanaged function without first pinning it, may the stack become corrupted?
您不应该在数组名称 (b) 上使用取址运算符 (&),因为数组名称本身已经是数组开头的地址。使用 &b
不起作用,结果行为将取决于多个因素(例如编译器及其设置)。
简单地说,调用函数时,您应该只传递数组名称 (b),而不是在数组名称 (&b) 上使用取址运算符。
顺便说一句,我相信您通过询问是否可以将堆栈上的托管值类型传递给 native 函数而不首先固定它来混淆问题,因为您给出的示例是传递非托管的堆栈 -基于 native 数组类型,与托管值类型无关。关于c++ - C++ CLR 值类型上需要 pin_ptr,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1105010/