Почему попытка объединения структуры вызывает исключение System.ExecutionEngineException? - PullRequest
1 голос
/ 13 июня 2011

Я попытался поэкспериментировать со способностью .NET поддерживать объединения, используя приведенный ниже код, но это вызывает исключение System.ExecutionengineException в .NET 2.0 и FatalExecutionEngineError в .NET 4.0 с сообщением:

Во время выполнения произошла фатальная ошибка.Адрес ошибки был 0x738b3138, в потоке 0x1080.Код ошибки 0xc0000005.Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях пользовательского кода.Распространенными источниками этой ошибки являются ошибки пользовательского маршалинга для COM-взаимодействия или 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 ]

1 голос
/ 14 июня 2011

Ваш код не поддается проверке, так как ссылки на объекты не должны перекрываться, что явно делают ваши поля poLine и soLine. В разделе 10.7 раздела II спецификации ECMA CLI указано:

Значения смещения должны быть неотрицательными. Таким способом можно перекрывать поля, хотя смещения, занятые ссылкой на объект, не должны перекрываться со смещениями, занятыми встроенным типом значения или частью другой ссылки на объект. Хотя одна ссылка на объект может полностью перекрывать другую, это невозможно проверить.

Далее вы можете проверить, что ваш код не поддается проверке, используя PEVerify (запустите peverify.exe для вашего исполняемого файла из командной строки Visual Studio) - он подтвердит, что код содержит ошибку.

Поэтому неудивительно, что вы видите исключение во время выполнения, и исключение, которое вы видите, кажется мне совершенно разумным (текст указывает, что оно может быть вызвано непроверяемым кодом) - что заставляет вас ожидать другого поведения

0 голосов
/ 13 июня 2011

Вы отображаете два ссылочных типа на одно и то же смещение. Это само по себе не является противозаконным, если вы не пытаетесь использовать оба одновременно, что именно здесь вы и пытаетесь сделать.

Это не ошибка, использование вами объединения просто неверно, и система справедливо жалуется. В родной среде указатель был бы перезаписан без предупреждения.

0 голосов
/ 13 июня 2011

Изменение второго смещения поля на 80 (или выше) решит вашу проблему.

Хотя я понятия не имею, что такое макет структуры и смещения, для чего вы их вообще используете?

Редактировать: О, только что заметил, что ваш вопрос, почему он дает эту ошибку, а не то, что ее вызывает, и сеть 4.0 говорит, что ошибка может быть вызвана повреждением стека, и вы объявляете переменную с тем же смещением, что и первоекоторый ... портит стек.С этой ошибкой проблем нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...