|
本文又名:《没有联合体引发的血案》。
UWP项目在通过.NET Native compiler编译时会报 ILT0005 错误,nutc_driver.exe 返回错误代码 -107374181,也就是十六进制的 0xC0000005,表示 Access Violation ,那排查的方向就有了:内存访问。
项目中某功能需要在内置整数类型比如Int32、UInt32等等中进行“切换”,所以我直接用此场景中最大整数类型Int64来当Buffer,通过泛型方法进行转换,泛型类型被unmanaged约束,所以代码类似:
unsafe static T ToUnmanagedT<T>(long buf) where T : unmanaged
{
return *(T*)&buf;
}
理论上没问题对吧?但其实不行,.NET Native编译器的BUG让其无法处理让包含这样的代码的项目。
我测试了各种情况,发现只有特定的表达式会引发这一问题:普通的非托管类型变量取址后转换为T类型指针后再解引用,即 *(T*)&var。 此表达式是左值也会引发这一错误,即:
unsafe static long ToLong<T>(T value) where T : unmanaged
{
long buf=0;
*(T*)&buf=value;
return buf;
}
并在通过.NET Native编译器通过以下配置进行编译时触发:
- ARM64
- RELEASE ARM
- RELEASE x64
解决的办法很简单,首先我们可以用中间变量:
unsafe static T ToUnmanagedT<T>(long buf) where T : unmanaged
{
T* t=(T*)&buf;
return *t;
}
也可以引入 System.Runtime.CompilerServices.Unsafe 包,通过 Unsafe.Read<T>() 和(或) Unsafe.Write<T>() 方法来完成:
unsafe static long ToLong<T>(T value) where T : unmanaged
{
long buf=0;
Unsafe.Write<T>(&buf, value);
return buf;
} |
|