לדלג לתוכן

פתרון גבולות unsafe ותחקיר

הפונקציה הבאה משתמשת באחסון מקומי רק בזמן ההרכבה ומחזירה העתק בבעלות נפרדת. האיפוס מגדיר את השדות השמורים של הכותרת ולא משאיר אותם תלויים בתוכן קודם של המחסנית.

using System.Buffers.Binary;

byte[] header = MakeHeader(7, 19);
Console.WriteLine(Convert.ToHexString(header));

static byte[] MakeHeader(uint kind, ulong length)
{
    Span<byte> temporary = stackalloc byte[16];
    temporary.Clear();
    BinaryPrimitives.WriteUInt32LittleEndian(temporary, kind);
    BinaryPrimitives.WriteUInt64LittleEndian(temporary[8..], length);
    return temporary.ToArray();
}

ה־API יכול היה במקום זאת לקבל Span יעד מן הקורא, לבדוק שהוא מכיל 16 byte-ים ולכתוב לתוכו בלי להקצות. בחוזה הנוכחי אין יעד חיצוני, ולכן נדרשת בעלות על אחסון שחי אחרי החזרה. החזרת pointer אל temporary אינה תיקון; היא משאירה reference לאזור שחייו הסתיימו.

בבדיקת הסכום ניצור Random עם seed קבוע, נמלא מערך ונשווה סכום מנוהל לסכום דרך pointer בתוך fixed עבור כל prefix. נכלול את האורך אפס, אבל לא נקרא בכוונה מחוץ לאזור כדי "לבדוק" raw pointer; זאת הפרת חוזה שעלולה להשחית את התהליך.

המסלול ב־dump עובר משדה סטטי אל List ומשם אל מערך ה־references ואל payload. ננקה את הרשימה ונצא מפונקציית הבנייה לפני המדידה השנייה. ה־KeepAlive מבטיח חיות של object עד נקודה, וה־fixed מבטיח יציבות כתובת בתחום. אף אחד מהם אינו נועל את התוכן מפני שינוי דרך alias אחר.