13

背景: 我正在使用 DirectX 9.0 托管库将 3d 点数组转换为 2d 屏幕坐标。为了速度,我使用 UnsafeNativeMethods 进行所有转换。

问题: 如果使用了我的自定义线剪辑功能,我的应用程序会死掉而没有抛出任何异常,我花了一段时间才发现它抛出了一个无法捕获 System.ExecutionEngineException的. 由于我的剪辑功能的最后两行,我将其缩小到发生。

List<Vector3> verticesAfterClipping = new List<Vector3>;
public unsafe void ClipLine(Line lineToClip)
{
    this.verticesAfterClipping.Clear();

    // Clipping algorithm happens here... (this is psuedo-code of what it does)
    foreach(Vertex in lineToClip.Vertices)
    {
        bool thisIsClipped =   // Set to whether this vertex is clipped
        bool lastWasClipped =  // Set to whether last vertex was clipped

        if(thisIsClipped == false && lastWasClipped == true)
        {
            verticesAfterClipping.Add( /* intersection on clipping plane */ );
            verticesAfterClipping.Add( /* thisVertex */ );
        }
        else if (thisIsClipped == false && lastWasClipped == false)
        {
            verticesAfterClipping.Add( /* thisVertex */ );
        }
        else if (thisIsClipped == true && lastWasClipped == false)
        {
            verticesAfterClipping.Add(/* intersection on clipping plane */);
        }
    }

    // THIS IS WHERE BAD THINGS HAPPEN
    lineToClip.Vertices = new Vertex[verticesAfterClipping.Count];
    verticesAfterClipping.CopyTo(lineToClip.Vertices, 0);
}

verticesAfterClipping列表被复制到lineToClip顶点时,lineToClip对象会被传递给 UnsafeNativeMethod,它将这些顶点转换为 2d 顶点。从我在调试模式下单步执行它时所看到的一切来看,它工作得非常好,直到它死掉。

我根本无法弄清楚出了什么问题。任何帮助将非常感激。

4

3 回答 3

26

问题实际上可能不会发生在引发异常的行中。这可能只是之前发生的事情的症状。

当CLR检测到出现严重错误System.ExecutionEngineException时,将引发异常。这可能会在问题发生后相当长的一段时间内发生。这是因为异常通常是内部数据结构损坏的结果——CLR 发现某些东西进入了没有意义的状态。它会抛出一个无法捕获的异常,因为继续进行是不安全的。

因此,您可能在系统的某个完全不相关的部分中有一些代码会破坏某些东西,但这只有在这段特定的代码运行时才会变得明显。您显示的代码可能很好。(也可能不是......我没有看到任何明显的错误,但是我不太了解 DX 9 托管库。例如,我看不出该方法的哪个功能需要 unsafe 关键字。 )

不幸的是,这意味着您需要开始将网络撒得更宽一些。几乎任何使用不安全代码或 COM 互操作的东西都可能受到怀疑。遗憾的是,这将是一个漫长而乏味的过程。您可能会采用的一种方法是尝试逐步简化程序:可以说明问题的最小代码是什么?(例如,如果您将此处显示的代码放入一个应用程序中,该应用程序只包含对该方法的最简单调用,它仍然会失败吗?)

于 2010-11-05T09:51:36.293 回答
2

我对不同的库有同样的问题。就我而言,这一切早在很久以前就开始了,因为我必须在 64 位环境中运行 32 位 .net 应用程序。嗯,这给我带来了很多麻烦,架构之间的兼容性,或者你的 .NET 框架的 CLR 之间的兼容性也可能是你的问题。

PS:现在我知道的问题是什么,但不知道它在哪里

于 2015-01-22T15:06:45.980 回答
0

我有两个类处理数据库中的特定表

StorageManager - 具有处理与数据库直接交互的方法的类

控制器 - 具有处理 api 调用的方法的类

当表中即将创建新条目时,我会检查子表中可能已经存在的某些值。

我编写了这些方法来检查错误类中的预先存在/重复项,这最终导致为我抛出执行引擎异常。

移动方法以便它们与正确的数据库上下文一起生活似乎对我来说解决了它。

于 2018-10-26T03:20:23.580 回答