2011-06-13 4 views
1

나는 아래의 코드를 사용하여 노동 조합을 지원하는 .NET의 능력을 실험하려고하지만 메시지와 함께 .NET 4.0에서 .NET 2.0 및 FatalExecutionEngineError에 System.ExecutionengineException가 발생합니다시도한 Union 구조가 System.ExecutionEngineException을 발생시키는 이유는 무엇입니까?

는 런타임이있다 치명적인 오류가 발생했습니다. 오류의 주소는 0x738b3138이고 스레드 0x1080에있었습니다. 오류 코드는 0xc0000005입니다. 이 오류 은 CLR 또는 사용자 코드의 안전하지 않거나 인증 할 수없는 부분 인 의 버그 일 수 있습니다. 이 버그의 일반적인 출처는 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 

답변

1

poLinesoLine 필드가 분명히하는 개체 참조가 겹치지 않아야하므로 코드를 확인할 수 없습니다. ECMA CLI spec의 파티션 II 섹션 10.7은 다음과 같이 명시하고 있습니다.

오프셋 값은 음수가 아닙니다. 개체 참조에 의해 점유 된 오프셋은 내장 된 값 형식이나 다른 개체 참조의 일부가 차지하는 오프셋과 겹치지 않지만이 방식으로 필드를 겹칠 수 있습니다. 하나의 객체 참조가 다른 객체 참조와 완전히 겹칠 수는 있지만이를 확인할 수는 없습니다.

당신은 더 코드를 PEVerify (Visual Studio 명령 프롬프트에서 실행 파일에 대한 실행 peverify.exe)를 사용하여 확인 불가능한 것을 확인할 수 있습니다 - 그것은 코드에 오류가 있는지 확인합니다.

따라서 런타임에 예외가 발생하는 것은 놀라운 일이 아니며보고있는 예외가 내게 완벽하게 합리적인 것으로 보입니다 (텍스트는 확인되지 않는 코드로 인해 발생할 수 있음을 나타냄) - 다른 것을 기대하는 원인 행동?

+0

.NET/CLI에는 "unverifiable"이라는 코드 카테고리가 있다는 것을 알지 못했습니다. 그게 관리되는 것과 안전하지 않은 것 중 어느 것입니까? "unverifiable"이라는 코드 카테고리입니까? 안전하지 않은 코드가 "안전하지 않은"블록에 포함되지 않은 경우 프로젝트에 포함되는 것을 방지 할 수 있다고 올바르게 기억합니까? 확인할 수없는 코드를 취급하는 PEVerify 외부에 (비슷한) 비슷한 것이 있습니까? "안전하지 않은"코드를 검증 할 수없는 다른 사례가 있습니까? – BlueMonkMN

+0

@BlueMonkMN - "안전하지 못함"과 "확인할 수없는"이 동의어라고 생각합니다. 'StructLayout' 속성의 사용이 C#과 VB.NET에서'/ unsafe' 스위치없이 허용된다는 것은 정말로 혼란 스럽습니다 (대조적으로 F #에서는 적어도 경고를 생성합니다). – kvb

+1

CLI 사양에서는 "확인할 수 없음"이라는 용어 만 사용합니다. "Unsafe"는 C#의 것으로, C# 스펙에 의해서만 정의됩니다. 이 두 용어는 실제로 겹쳐 지지만 동일하지는 않습니다.이 질문에서 알 수 있듯이 CLI에서 확인할 수없는 코드는 C# -unsafe 범주에 속하지 않을 수 있습니다. 반면에 C# -unsafe는 항상 확인할 수 없습니다. –

0

두 번째 필드 오프셋을 80 이상으로 변경하면 문제가 해결됩니다.

구조체 레이아웃과 오프셋이 모두 무엇인지 잘 모르겠지만 무엇을 사용하고 있습니까?

편집 : 아 그냥 귀하의 질문에 왜이 오류를 일으키는 원인이 무엇인지 및 4.0 net 그 오류가 스택 손상으로 인해 발생할 수 있습니다 말한다 및 첫 번째 같은 오프셋에 변수를 선언합니다 하나는 ... 스택을 부패시킵니다. 그 오류에는 아무런 문제가 없습니다.

+0

나는 관리 코드가 안전하지 않은 것으로 명시하지 않고 손상된 (안전하지 않은 것으로 간주 될 수 있음) 것을 허용하지 않았다고 생각했습니다. 그래서이 테스트를 실행하여 잠재적으로 안전하지 않은 방식으로이 구조체에 액세스하려는 시도를 처리하는 방법을 확인했습니다. – BlueMonkMN

0

두 참조 유형을 동일한 오프셋에 매핑합니다. 동시에 그 두 가지를 동시에 사용하려고하지 않는 한 그 자체로 불법이 아닙니다. 정확히 여기에서하려고하는 것입니다.

이것은 버그가 아니며, 유니온의 사용법이 잘못되어 시스템이 올바르게 불만을 제기합니다. 네이티브 환경에서는 포인터가 자동으로 덮어 쓰여집니다.

+0

그건 정확히 내 요점이야. 앞에서 말했듯이, 코드는 작동하지 않아야합니다. 그러나 던지는 예외의 종류는 이해가되지 않습니다. – BlueMonkMN

+0

@Blue - 나는 당신의 요점을 본다; 나는 그 질문을 오해했다. 나는 궁금한데 예외는 어디에서 던져 질까? 덮어 쓴 인스턴스를 사용하려고하거나 덮어 쓴 즉시 사용하려고합니까? 나중에, 코드는 여전히 기술적으로 안전합니다. 관리 환경없이 즉시 다른 인스턴스를 덮어 쓰지 않아 치명적인 오류가 발생할 수 있으므로 코드가 여전히 안전합니다. – Coincoin

+0

두 번째 WriteLine에서 발생합니다. – BlueMonkMN

관련 문제