这种不安全的代码是否也可以在.NET Core 3中使用? - c#

我正在重构我的库,以尽可能使用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 Web应用程序中增加JSON反序列化MaxDepth限制 - c#

我们正在将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 …