Span<T>
Mümkünse yığın ayırmalarını önlemek için kullanmak üzere kütüphanelerimi yeniden düzenliyorum, ancak daha eski çerçeveleri de hedeflediğim için bazı genel yedek çözümler de uyguluyorum. Ama şimdi garip bir sorun buldum ve .NET Core 3'te bir hata bulduğumdan mı yoksa yasadışı bir şey mi yaptığımdan emin değilim.
Sorun:
// 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;
}
İlginçtir, ReinterpretOld
.NET Framework ve .NET Core 2.0'da iyi çalışır (sonuçta bundan memnun olabilirim), yine de beni biraz rahatsız ediyor.
Btw. ReinterpretOld
.NET Core 3.0'da küçük bir değişiklikle de düzeltilebilir:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
Benim sorum:
Bu bir hata mıdır yoksa ReinterpretOld
eski çerçevelerde yalnızca yanlışlıkla mı çalışır ve düzeltmeyi onlar için de uygulamalıyım?
Uyarılar:
- Hata ayıklama derlemesi .NET Core 3.0'da da çalışır
- Ben uygulamak için çalıştı
[MethodImpl(MethodImplOptions.NoInlining)]
etmekReinterpretOld
ama hiçbir etkisi olmadı.
Span<T>
gereken iki versiyon farklı IL'ye derlenir. Ben yok bence sen şey geçersiz Güncel yapıyoruz: Bir JIT hata şüpheli.
stackalloc
(yani ayrılan alanı silmez)
return Unsafe.As<byte, uint>(ref bytes[0]);
veyareturn MemoryMarshal.Cast<byte, uint>(bytes)[0];
- kullanmaya gerek yokGetPinnableReference()
; diğer