我尝试搜索但没有找到任何东西,但是当将int []作为指针传递给本机DLL函数时,DLL仍然存在维护对指针的引用的危险,并且然后在“固定”块终止后再次尝试访问它?如果GC移动了您的阵列,这不会导致内存访问错误吗?如果是这样,你怎么解决这个问题?或者这是不太可能的情况?
答案 0 :(得分:11)
更新:此问题是my blog on December 11th 2012的主题。谢谢你提出的好问题!
尝试搜索但未找到任何内容
如果您对语言有疑问,请考虑阅读语言规范。
将int []作为指针传递给本机DLL函数时,DLL是否仍然存在对指针的引用的危险,然后在“fixed”块之后再次尝试访问它终止?
是的。正如语言规范所述:
这是程序员的责任 确保创建指针 固定的陈述不能超越 执行那些陈述。对于 例如,当由指针创建时 固定语句传递给 外部API,它是程序员的 有责任确保API 保留对这些指针的记忆。
如果GC移动了您的阵列,这不会导致内存访问错误吗?
是!
如果是这样,你怎么解决这个问题?
你没有。正如语言规范所述,你必须永远不要那样做。既然你永远不会这样做,你就不必找到办法绕过它。这就像是在问“我如何从致命的自我中恢复过来?”你没有 - 如果你不想最终死亡,那么一个好的规则就是“不要在第一时间向自己开枪”。
或者这是不太可能出现的情况?
您是否可能编写调用违反托管代码规则的DLL的C#程序? 我不知道!你告诉我 - 你觉得你可能会想做什么?
答案 1 :(得分:1)
这是我为修复问题所做的课程。它使用AllocHGlobal在非托管中创建一个内存空间,然后将指针包装到该空间。不幸的是,制作这种通用似乎不起作用,因为我无法在void*
方法中找到从T
转换为this[int i]
的内容。
unsafe sealed class FixedFloatArray : IDisposable {
readonly float* _floats;
internal FixedFloatArray(int size) {
_floats = (float*)Marshal.AllocHGlobal(sizeof(float) * size);
}
internal FixedFloatArray(float[] floats) {
_floats = (float*)Marshal.AllocHGlobal(sizeof(float) * floats.Length);
Marshal.Copy(floats, 0, (IntPtr)_floats, floats.Length);
}
internal float this[int i] {
get { return _floats[i]; }
set { _floats[i] = value; }
}
internal void CopyFrom(float[] source, int sourceIndex, int destinationIndex, int length) {
var memoryOffset = (int)_floats + destinationIndex * sizeof(float);
Marshal.Copy(source, sourceIndex, (IntPtr)memoryOffset, length);
}
internal void CopyTo(int sourceIndex, float[] destination, int destinationIndex, int length) {
var memoryOffset = (int)_floats + sourceIndex * sizeof(float);
Marshal.Copy((IntPtr)memoryOffset, destination, destinationIndex, length);
}
public static implicit operator IntPtr(FixedFloatArray ffa) {
return (IntPtr)ffa._floats;
}
public void Dispose() {
Marshal.FreeHGlobal((IntPtr)_floats);
}
}