IE盒子

搜索
查看: 161|回复: 2

ILT0005:由非托管代码引发的少见.NET Native compiler问题 ...

[复制链接]

5

主题

6

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2022-9-22 08:30:12 | 显示全部楼层 |阅读模式
本文又名:《没有联合体引发的血案》。
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;
}
回复

使用道具 举报

4

主题

8

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2022-9-22 08:30:54 | 显示全部楼层
你不考虑数据的长度吗?
回复

使用道具 举报

0

主题

8

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-9-22 08:31:47 | 显示全部楼层
内部实施不用考虑数据大小,外部使用可以用 Marshal.SizeOf 验证。ILT0005不是因为代码错误,而是编译器分析功能有问题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表