ฉันปรับโครงสร้างห้องสมุดของฉันเพื่อใช้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 (ดังนั้นฉันจะมีความสุขกับมันหลังจากทั้งหมด) ยังคงมันรบกวนฉันเล็กน้อย
Btw ReinterpretOld
สามารถแก้ไขได้ใน. NET Core 3.0 ด้วยการปรับเปลี่ยนเล็กน้อย:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
คำถามของฉัน:
นี่เป็นข้อบกพร่องหรือReinterpretOld
ทำงานในกรอบงานที่เก่ากว่าโดยไม่ได้ตั้งใจเท่านั้นและฉันควรใช้การแก้ไขกับพวกเขาด้วยหรือไม่
หมายเหตุ:
- การตรวจแก้จุดบกพร่องทำงานได้ใน. NET Core 3.0
- ผมพยายามที่จะนำไปใช้
[MethodImpl(MethodImplOptions.NoInlining)]
ในการReinterpretOld
แต่ก็ไม่มีผล
stackalloc
(เช่นไม่ให้ลบพื้นที่ที่จัดสรรไว้)
return Unsafe.As<byte, uint>(ref bytes[0]);
หรือreturn MemoryMarshal.Cast<byte, uint>(bytes)[0];
- ไม่จำเป็นต้องใช้GetPinnableReference()
; มองไปที่อีกนิด