对固定块内的指针所做的更改是否保留?

时间:2013-11-26 10:45:53

标签: c# c++ pointers unity3d native-code

请查看以下c#代码:

    double* ptr;

    fixed(double* vrt_ptr = &vertices[0])
    {
        fixed(int* tris_ptr = &tris[0])
        {
            ptr = compute(vrt_ptr, 5, (double*)tris_ptr, 5);
// compute() is a native C++ function 
        }
    }

    Debug.Log("Vertices Recieved: " + *ptr);
/* and so on */

我从* ptr获得垃圾值。我怀疑由ptr分配给compute的数组不会保留在外部固定块之外。是这样吗??或者是由于其他一些问题?

1 个答案:

答案 0 :(得分:3)

这是有效代码,垃圾收集器只能更新vrt_ptrtris_ptr变量的值。但是非托管代码使用这些指针的 copy ,GC无法更新副本的值。因此,如果在非托管代码运行时发生,则可能发生垃圾收集,例如当程序中的其他线程触发集合时,非托管代码将通过指针副本读取垃圾数据。很难诊断,经常不会发生。

必须固定顶点和tris数组。在您的情况下,pinvoke marshaller已经完成了,只需直接传递数组而不使用 fixed 。修正:

   double* ptr = compute(vertices, 5, tris, 5);

相应地调整pinvoke声明,用double []替换double *。

您现在还必须处理您首先编写此代码的可能原因。有没有的场景,其中将int []转换为double []是有效的,这可能是因为你在GC灾难发生之前就得到了垃圾结果。如果由于某种原因无法更新 tris 的声明,则必须在通话前创建一个double []。