为什么此代码抛出System.ExecutionEngineException

tbr*_*dge 11 c# exception managed-directx

背景: 我使用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);
}
Run Code Online (Sandbox Code Playgroud)

verticesAfterClipping列表复制到lineToClip顶点时,lineToClip对象将传递给UnsafeNativeMethod,后者将这些顶点转换为2d顶点.从我在调试模式中逐步完成它时可以看到的一切,它完全正常,直到它完全消失.

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

Ian*_*ths 17

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

System.ExecutionEngineException当CLR抛出异常检测的是什么地方出了可怕的错误.这可能在问题发生后相当长的一段时间内发生.这是因为异常通常是内部数据结构损坏的结果--CLR发现某些东西已进入一种无意义的状态.它抛出一个无法捕获的异常,因为它不安全.

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

不幸的是,这意味着你需要开始更宽一点的网络.几乎任何使用不安全代码或COM互操作的东西都可能是可疑的.遗憾的是,这将是一个漫长而乏味的过程.您可能采用的一种方法是尝试逐步简化程序:可以说明问题的最小代码是什么?(例如,如果你把你在那里显示的代码放到一个除了对该方法最简单的调用之外什么都没有的应用程序中,它仍然会失败吗?)

  • 不要认为缺少ExecutionEngineException意味着问题已经消失.可能仅仅是CLR不再检测它.通过替换这些行,您现在可能处于数据损坏的情况,但您不再获得异常.(CLR不会也不能保证在任何这样的事情发生错误的时候抛出ExecutionEngineException.它只会在碰巧注意时抛出它.)所以我会担心 - 我肯定会试图找到底部*如何*崩溃发生,就像现在一样,没有理由相信你已经真正解决了它. (4认同)