为什么这段代码会抛出 System.ExecutionEngineException
背景: 我正在使用 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 顶点。从我所看到的一切来看,当我在调试模式下单步执行它时,它工作得很好,直到它死掉。
我根本不明白出了什么问题。任何帮助将不胜感激。
Background:
I am using DirectX 9.0 Managed Libraries to transform arrays of 3d points to 2d screen coordinates. For speed I use the UnsafeNativeMethods to do all the transformations.
The Problem:
If my custom line clipping function is used my application dies without throwing any exceptions, it took me a while to figure out that it was throwing an uncatchable System.ExecutionEngineException
. I have narrowed it down to happening because of the last two lines of my clipping function.
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);
}
When the verticesAfterClipping
list is copied to the lineToClip
vertices the lineToClip
object is then passed to an UnsafeNativeMethod which transforms these vertices to 2d vertices. From everything I can see when I step through it in Debug mode it is working completely fine, until it just dies.
I simply cannot figure out what is wrong. Any help would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题实际上可能并未发生在引发异常的行中。这可能只是之前发生的事情的征兆。
当 CLR 检测到出现严重错误时,会引发 System.ExecutionEngineException 异常。这种情况可能会在问题发生一段时间后发生。这是因为异常通常是内部数据结构损坏的结果 - CLR 发现某些内容已进入无意义的状态。它会引发无法捕获的异常,因为继续操作不安全。
因此,您可能在系统的某个完全不相关的部分中有一些代码破坏了某些内容,但这只有在这段特定代码运行时才会变得明显。您显示的代码可能没问题。 (也可能不是......我没有看到任何明显的错误,但我不太了解 DX 9 托管库。例如,我看不出此方法的哪个功能需要 unsafe 关键字。 )
不幸的是,这意味着你需要开始把网撒得更广一些。几乎所有使用不安全代码或 COM 互操作的内容都可能受到怀疑。遗憾的是,这将是一个漫长而乏味的过程。您可能采取的一种方法是尝试逐渐简化程序:可以说明问题的最小代码段是什么? (例如,如果您将在那里显示的代码放入一个应用程序中,该应用程序除了对该方法的最简单的调用之外不包含任何其他内容,它仍然会失败吗?)
The problem may not actually be occurring in the line that throws an exception. This may just be a symptom of something that happened earlier.
The
System.ExecutionEngineException
exception is thrown when the CLR detects that something has gone horribly wrong. This can happen some considerable time after the problem occurred. This is because the exception is usually a result of corruption of internal data structures - the CLR discovers that something has got into a state that makes no sense. It throws an uncatchable exception because it's not safe to proceed.So you might have some code in some completely unrelated part of the system that corrupts something, but this only becomes apparent when this particular piece of code runs. The code you've shown might be just fine. (It also might not be...I don't see anything obvious wrong, but then I don't know the DX 9 managed libraries well. I can't see which feature of this method requires the unsafe keyword, for example.)
Unfortunately, this means you need to start casting the net a bit wider. Pretty much anything that uses either unsafe code, or COM interop is potentially suspect. This will be a long and tedious process, sadly. One way you might approach it is to try gradually simplifying the program: what's the smallest piece of code that can illustrate the problem? (E.g., if you put the code you've shown there into an application that contains nothing else except the simplest possible call to that method, does it still fail?)
我对不同的库有同样的问题。就我而言,一切都很早就开始了,因为我必须在 64 位环境中运行 32 位 .net 应用程序。这给我带来了很多麻烦,架构之间的兼容性,或者.NET框架的CLR之间的兼容性也可能是你的问题。
PS:现在我知道我的麻烦是什么,但不知道它在哪里。
I have the same problem with different libraries. In my case all started long before because I had to run a 32 bit .net app in a 64 bit environment. Well this cause me a lot of trouble, the compatibility between architectures, or between the CLR of your .NET framework may be your problem too.
PS: Now I know what my trouble is but have no idea where is it.
我有两个类处理数据库中的特定表
StorageManager - 一个具有处理与数据库直接交互的方法的类
Controller - 一个具有处理 api 调用的方法的类
当表中的新条目即将出现时创建后,我检查子表中可能已经存在的某些值。
我编写这些方法是为了检查错误的类中是否存在预先存在的/重复项,这最终导致为我抛出executingengineException。
移动这些方法,使它们能够使用正确的数据库上下文似乎可以解决这个问题。
I have two classes that deal with a particular table in my database
StorageManager - a class that has methods that handle the direct interactions with the database
Controller - a class that has methods to handle the api calls
When a new entry in the table is about to be created, I check child tables for certain values that might already exist.
I wrote these methods to check for pre-existing/duplicates in the wrong class, which ended up causing the executingengineexception to get thrown for me.
Moving the methods so that they lived with the correct database context seemed to fix it for me.