我正在重构我的库,以尽可能使用Span<T>
避免堆分配,但是由于我也针对较旧的框架,因此我也在实现一些常规的后备解决方案。但是现在我发现了一个奇怪的问题,我不确定我是否在.NET Core 3中发现了错误,或者我是否在做违法的事情。
问题:
// This returns 1 as expected but cannot be used in older frameworks:
private static uint ReinterpretNew()
{
Span<byte> bytes = stackalloc byte[4];
bytes[0] = 1; // FillBytes(bytes);
// returning bytes as uint:
return Unsafe.As<byte, uint>(ref bytes.GetPinnableReference());
}
// This returns garbage in .NET Core 3.0 with release build:
private static unsafe uint ReinterpretOld()
{
byte* bytes = stackalloc byte[4];
bytes[0] = 1; // FillBytes(bytes);
// returning bytes as uint:
return *(uint*)bytes;
}
有趣的是,ReinterpretOld
在.NET Framework和.NET Core 2.0中都可以很好地工作(毕竟我可以对此感到满意),但是,这仍然让我有些困扰。
顺便说一句。只需稍作修改,即可在.NET Core 3.0中修复ReinterpretOld
:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
我的问题:
这是一个错误还是ReinterpretOld
只能在偶然的情况下在较旧的框架中工作,我是否也应该对它们应用此修复程序?
备注:
调试版本也可以在.NET Core 3.0中使用
我尝试将[MethodImpl(MethodImplOptions.NoInlining)]
应用于ReinterpretOld
,但没有效果。
参考方案
哦,这是一个有趣的发现;这里发生的事情是您的本地计算机正在被优化-没有本地计算机剩余,这意味着没有.locals init
,这意味着stackalloc
的行为有所不同,并且不会擦除空间;
private static unsafe uint Reinterpret1()
{
byte* bytes = stackalloc byte[4];
bytes[0] = 1;
return *(uint*)bytes;
}
private static unsafe uint Reinterpret2()
{
byte* bytes = stackalloc byte[4];
bytes[0] = 1;
uint* asUint = (uint*)bytes;
return *asUint;
}
变成:
.method private hidebysig static uint32 Reinterpret1() cil managed
{
.maxstack 8
L_0000: ldc.i4.4
L_0001: conv.u
L_0002: localloc
L_0004: dup
L_0005: ldc.i4.1
L_0006: stind.i1
L_0007: ldind.u4
L_0008: ret
}
.method private hidebysig static uint32 Reinterpret2() cil managed
{
.maxstack 3
.locals init (
[0] uint32* numPtr)
L_0000: ldc.i4.4
L_0001: conv.u
L_0002: localloc
L_0004: dup
L_0005: ldc.i4.1
L_0006: stind.i1
L_0007: stloc.0
L_0008: ldloc.0
L_0009: ldind.u4
L_000a: ret
}
我想很高兴地说这是一个编译器错误,或者至少是:考虑到previous decisions have been put in place to say "emit the .locals init"的不良副作用和行为,尤其是试图保持stackalloc
的正常运行-但是编译器人们是否同意是一个问题。由他们决定。
解决方法是:将stackalloc
空间视为未定义的空间(公平地说,这就是您要执行的操作);如果您希望它为零:请手动将其归零。
我们正在将ASP.NET Core 2.1与.NET Framework 4.6.2结合使用。我们有一个客户需要向我们的Web应用程序发送一个很大程度上嵌套的json结构。当他们进行此调用时,我们将输出以下日志并返回错误: 读取器的MaxDepth超过了32。路径“ super.long.path.to property”,第1行,位置42111。”我浏览了…
ASP.NET Core-在Singleton注入上存储库依赖项注入失败 - c#我正在使用SoapCore为我的ASP.NET Core MVC应用程序创建Web服务。我正在使用Entity Framework Core和简单的存储库模式来获取我的数据库数据。我通过Startup.cs中的.AddSingleton()注入存储库类:services.AddSingleton<IImportRepository, ImportRep…
从Axios请求以ASP.NET Core API返回下载文件 - c#大家好我正在尝试从Axios Request从ASP.NET Core Web API下载文件。这是我的示例API方法。 (基于此stackoverflow question的代码)[HttpPost("download")] public async Task<IActionResult> DownloadFile(){ .…
从.NET Core 2.1降级到.NET 4.7.1时,如何使用IApplicationBuilder和IServiceCollection? - c#我不得不将我的项目从.NET Core 2.1更改为.NET 4.7.1,并且修复了几乎所有错误,但以下错误仍然困扰着我 “ IApplicationBuilder”不包含“ UseHsts”的定义,也找不到找不到接受类型为“ IApplicationBuilder”的第一个参数的扩展方法“ UseHsts”(是否缺少using指令或程序集引用?) “ IA…
在ASP.NET Core 2.1中添加自定义TagHelpers - c#我严格按照ASP.NET Core文档进行操作,并花费了大量时间来拖曳堆栈溢出,试图实现简单的自定义TagHelper,但没有成功。任何人都可以就任何陷阱或已知错误提出建议吗?应用程序属性:AssemblyName: AmpWeb Target Framework .NET Core 2.1 NuGet软件包Microsoft.AspNetCore.All …