【问题标题】:Changes made to a pointer inside a fixed block retain or not?对固定块内的指针所做的更改是否保留?
【发布时间】:2013-12-11 11:11:46
【问题描述】:

请看下面的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 的垃圾值。我怀疑compute 分配给ptr 的数组不会保留在固定块之外。是这样吗??还是因为其他问题?

【问题讨论】:

  • 可能,compute 返回一个指向局部变量的指针,函数返回时销毁。但是不看函数就无法知道。
  • @MikeSeymour 本地变量的指针不会在方法返回后立即销毁。不是吗?
  • @SriramSakthivel:当程序离开其作用域时,局部变量将被销毁,任何指向它的指针都将指向垃圾。
  • @MikeSeymour 看来compute 是c++ 方法。我想这是relevant。我可能错了。有错请指正。
  • 我认为在调用compute之前分配它并交给它会更好。这样你可以摆脱虚假的ptr,如果你稍后释放内存会更清楚(为了防止内存泄漏)。

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


【解决方案1】:

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

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

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

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

您现在还必须处理最初编写此代码的可能原因。 没有场景将 int[] 转换为 double[] 是永远有效的,这可能是您在 GC 灾难发生之前得到垃圾结果的可能原因。如果由于某种原因您无法更新 tris 的声明,那么您必须在调用之前创建一个 double[]。

【讨论】:

    猜你喜欢
    • 2017-01-13
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-02
    • 2021-03-14
    • 1970-01-01
    相关资源
    最近更新 更多