为什么尝试的Union结构会导致System.ExecutionEngineException?

时间:2011-06-13 16:31:13

标签: .net vb.net clr union

我尝试使用下面的代码试验.NET支持联合的能力,但它在.NET 4.0中导致System.ExecutionengineException,在.NET 4.0中导致FatalExecutionEngineError,并显示消息:

  

运行时遇到了致命错误   错误。错误的地址是   0x738b3138,在线程0x1080上。该   错误代码是0xc0000005。这个错误   可能是CLR或中的错误   不安全或不可核实的部分   用户代码。这个bug的常见来源   包括用户封送错误   COM-interop或PInvoke,可能   腐败堆栈。

我同意此代码不起作用,但我没想到会出现这种异常。这是一个.NET错误吗?

Class POLine
  Public price As Decimal
  Public VendorItem As String
End Class

Class SOLine
  Public price As Decimal
  Public Required As DateTime
End Class

<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)> _
Structure LineRef
  <System.Runtime.InteropServices.FieldOffset(0)> _
  Public poLine As POLine
  <System.Runtime.InteropServices.FieldOffset(0)> _
  Public soLine As SOLine
End Structure

Sub Main()
  Dim lr As New LineRef
  lr.poLine = New POLine With {.price = 1.23D, .VendorItem = "X22"}
  lr.soLine = New SOLine With {.price = 3.14D, .Required = DateTime.Now}
  Console.WriteLine("{0} {1}", lr.soLine.price, lr.soLine.Required)
  Console.WriteLine("{0} {1}", lr.poLine.price, lr.poLine.VendorItem)
End Sub

3 个答案:

答案 0 :(得分:1)

您的代码无法验证,因为对象引用不应重叠,而poLinesoLine字段显然不会重叠。正如ECMA CLI spec州第二部分第10.7节所述:

  

偏移值应为非负值。虽然对象引用占用的偏移量不应与内置值类型或另一个对象引用的一部分占用的偏移量重叠,否则可以以这种方式重叠字段。虽然一个对象引用可以完全与另一个对象引用重叠,但这是无法验证的。

您可以使用PEVerify进一步检查您的代码是无法验证的(从Visual Studio命令提示符对您的可执行文件运行peverify.exe) - 它将确认代码包含错误。

因此,在运行时看到异常并不奇怪,您看到的异常对我来说似乎完全合理(文本表明它可能是由无法验证的代码引起的) - 是什么导致您期望不同的行为?

答案 1 :(得分:0)

将第二个字段偏移更改为80(或更高)将解决您的问题。

虽然我不知道所有的结构布局和偏移是什么,你甚至用它们做什么?

编辑:哦,只是注意到你的问题是为什么它给出了这个错误,而不是导致它的原因,4.0网表示错误可能是由于损坏堆栈引起的,并且你声明一个变量与第一个相同的偏移量哪...破坏了堆栈。这个错误没有问题。

答案 2 :(得分:0)

您将两个引用类型映射到相同的偏移量。只要你不试图同时使用两者,这本身并不违法,这正是你在这里尝试做的。

这不是一个错误,你对联盟的使用是完全错误的,系统正当地抱怨。在原生环境中,指针会被静默覆盖。