ConstructiCat Logo
CodeBust.
Browse section ▾

الرقم السحري (البرمجة).

قيمة عددية ذات معنى غير واضح

في برمجة الحاسوب، يُقصد بـالرقم السحري أو توقيع الملف قيمةٌ عددية حرفية في الشيفرة المصدرية ذات معنى خاص ومحدد لكنه أقل وضوحًا للقارئ. وكذلك في الحوسبة، وليس في البرمجة وحدها، يُستخدم المصطلح للإشارة إلى رقم يُعرّف مفهومًا معينًا لكن معناه يبقى أقل من واضح بدون معرفة إضافية. فعلى سبيل المثال، تُعرَّف بعض صيغ الملفات برقم سحري مُضمَّن في الملف ). كذلك قد يُصنَّف رقمٌ مرتبطٌ ارتباطًا فريدًا نسبيًا بمفهوم معين، مثل المُعرّف الفريد عالميًا، على أنه رقم سحري.

القيمة الحرفية العددية

الـرقم السحري أو الـثابت السحري هو قيمة حرفية عددية في الشيفرة المصدرية ذات معنى خاص لكنه أقل وضوحًا في سياقه. ويُعدّ هذا نمطًا مضادًا يخالف واحدة من أقدم قواعد البرمجة، التي تعود إلى أدلة كوبول وفورتران وPL/1 في ستينيات القرن العشرين.

على سبيل المثال، في الشيفرة التالية التي تحسب السعر بعد الضريبة، يُعدّ 1.05 رقمًا سحريًا لأن القيمة تُرمّز معدّل ضريبة المبيعات، 5%، بطريقة أقل من واضحة.

price_after_tax = 1.05 * price

إن استخدام الأرقام السحرية في الشيفرة يحجب نيّة المطورين من اختيار ذلك الرقم، ويزيد من فرص حدوث أخطاء خفية، ويجعل تكييف البرنامج وتوسيعه مستقبلًا أكثر صعوبة. وكمثال، يصعب معرفة ما إذا كانت كل خانة في 3.14159265358979323846 قد كُتبت بشكل صحيح، أو ما إذا كان من الممكن اقتطاع هذا الثابت الخاص بـباي إلى 3.14159 دون التأثير في وظيفة البرنامج رغم دقته المنخفضة. إن استبدال كل الأرقام السحرية المهمّة بـثوابت مُسمّاة (تُسمّى أيضًا متغيرات توضيحية) يجعل البرامج أسهل في القراءة والفهم والصيانة.

يمكن تحسين المثال أعلاه بإضافة متغير ذي اسم وصفي:

TAX = 0.05
price_after_tax = (1.0 + TAX) * price

يمكن للاسم الجيد أن ينتج عنه شيفرة أسهل في الفهم على من يصونها وليس مؤلفها الأصلي، بل وحتى على المؤلف الأصلي بعد مرور فترة من الزمن. ومن أمثلة الثابت ذي الاسم غير المفيد int SIXTEEN = 16، في حين قد يكون int NUMBER_OF_BITS = 16 أكثر فائدة.

يمكن للبيانات غير العددية أن تحمل الخصائص السحرية ذاتها، وبالتالي المشكلات ذاتها التي تحملها الأرقام السحرية. لذا فإن التصريح بـconst string testUserName = "John" واستخدام testUserName قد يكون أفضل من استخدام القيمة الحرفية "John" مباشرة.

مثال

على سبيل المثال، إذا لزم خلط القيم عشوائيًا في مصفوفة تمثّل رزمة قياسية من أوراق اللعب، فإن هذه الشيفرة الزائفة تؤدي المهمة باستخدام خوارزمية خلط فيشر–ييتس:

for i from 1 to 52
    j := i + randomInt(53 - i) - 1
    a.swapEntries(i, j)

حيث a كائن مصفوفة، والدالة randomInt(x) تختار عددًا صحيحًا عشوائيًا بين 1 وx شاملًا الطرفين، وتُبدّل swapEntries(i, j) العنصرين i وj في المصفوفة. في المثال السابق، يُعدّ 52 و53 رقمين سحريين، وليس من الواضح أيضًا كيف يرتبطان ببعضهما. ويُعدّ من الأفضل أسلوبيًا في البرمجة كتابة ما يلي:

int deckSize:= 52
for i from 1 to deckSize
    j := i + randomInt(deckSize + 1 - i) - 1
    a.swapEntries(i, j)

وهذا أفضل لعدة أسباب:

  • قابلية قراءة أفضل. قد يتساءل مبرمج يقرأ المثال الأول: ماذا يعني الرقم 52 هنا؟ ولماذا 52؟ قد يستنتج المبرمج المعنى بعد قراءة الشيفرة بعناية، لكنه ليس بديهيًا. وتصبح الأرقام السحرية مربكة بوجه خاص عندما يُستخدم الرقم نفسه لأغراض مختلفة في قسم واحد من الشيفرة.
  • أسهل في الصيانة. من الأسهل تغيير قيمة الرقم لأنها غير مكررة. إن تغيير قيمة رقم سحري عُرضة للخطأ، لأن القيمة نفسها كثيرًا ما تُستخدم عدة مرات في أماكن مختلفة داخل البرنامج. كذلك، عندما يحمل متغيران أو رقمان متمايزان دلاليًا القيمة نفسها، فقد يُعدَّلان معًا عرضًا. ولتعديل المثال الأول كي يخلط رزمة تاروت، التي تضم 78 ورقة، قد يستبدل المبرمج بسذاجة كل ظهور للرقم 52 في البرنامج بالرقم 78. وهذا يسبب مشكلتين. أولاً، سيُغفِل القيمة 53 في السطر الثاني من المثال، مما يجعل الخوارزمية تفشل بطريقة خفية. ثانيًا، من المرجح أن يستبدل الحرفين «52» في كل مكان، بصرف النظر عمّا إذا كانا يشيران إلى حجم الرزمة أو إلى شيء آخر مختلف تمامًا، كعدد أسابيع السنة في التقويم الميلادي، أو على نحو أكثر خبثًا، أن يكونا جزءًا من رقم مثل «1523»، وكل ذلك من شأنه أن يُدخل أخطاءً برمجية. وعلى النقيض، فإن تغيير قيمة المتغير deckSize في المثال الثاني سيكون تغييرًا بسيطًا في سطر واحد.
  • يشجّع على التوثيق. يوفّر المكان الوحيد الذي يُصرَّح فيه عن المتغير المُسمّى موضعًا جيدًا لتوثيق ما تعنيه القيمة ولماذا حملت القيمة التي حملتها. أما وجود القيمة نفسها في عدد وفير من الأماكن فإما أن يؤدي إلى تعليقات مكررة (وما يصحبها من مشكلات عند تحديث بعضها وإغفال بعضها الآخر)، أو لا يترك أيّ مكانٍ واحد يكون فيه من الطبيعي للمؤلف أن يشرح القيمة ومن المرجح أن يبحث فيه القارئ عن شرح.
  • يجمّع المعلومات. يمكن وضع تصريحات متغيرات «الأرقام السحرية» معًا، عادةً في أعلى دالة أو ملف، مما يسهّل مراجعتها وتغييرها.
  • يكشف الأخطاء المطبعية. إن استخدام متغير (بدلًا من قيمة حرفية) يستفيد من فحص المترجم. فكتابة «62» عرضًا بدلًا من «52» ستمرّ دون كشف، في حين أن كتابة «dekSize» بدلًا من «deckSize» ستؤدي إلى تحذير المترجم بأن dekSize غير مُصرَّح به.
  • يقلّل من الكتابة. إذا كانت بيئة التطوير المتكاملة تدعم إكمال الشيفرة، فستملأ معظم اسم المتغير انطلاقًا من أحرفه القليلة الأولى.
  • يسهّل المعاملة الوسيطية. على سبيل المثال، لتعميم المثال أعلاه إلى إجراء يخلط رزمة بأي عدد من الأوراق، يكفي تحويل deckSize إلى وسيط لذلك الإجراء، في حين أن المثال الأول سيتطلب عدة تغييرات.
function shuffle (int deckSize)
   for i from 1 to deckSize
       j := i + randomInt(deckSize + 1 - i) - 1
       a.swapEntries(i, j)

أما العيوب فهي:

  • يكسر المحلّية. عندما لا يُعرَّف الثابت المُسمّى قرب موضع استخدامه، فإن ذلك يضرّ بمحلّية الشيفرة وبالتالي بقابليتها للفهم. إن وضع الرقم 52 في مكان قد يكون بعيدًا يعني أنه لفهم آلية عمل حلقة «for» فهمًا كاملًا (مثلًا لتقدير زمن تشغيل الحلقة)، يجب على المرء تتبّع التعريف والتحقق من أنه الرقم المتوقَّع. ومن السهل تجنّب ذلك (بإعادة موضع التصريح) عندما يُستخدم الثابت في جزء واحد فقط من الشيفرة. أما عندما يُستخدم الثابت المُسمّى في أجزاء متفرقة، فإن الموقع البعيد يكون دلالةً للقارئ على أن القيمة نفسها تظهر في أماكن أخرى من الشيفرة، وقد يستحق ذلك النظر فيه أيضًا.
  • يسبّب الإطناب. يضيف تصريح الثابت سطرًا. وعندما يكون اسم الثابت أطول من قيمته، خاصةً إذا ظهرت عدة ثوابت من هذا النوع في سطر واحد، فقد يستلزم ذلك تقسيم عبارة منطقية واحدة من الشيفرة على عدة أسطر. وقد تكون الزيادة في الإطناب مبرَّرة عندما يكون هناك احتمال للبس حول الثابت، أو عندما يكون هناك احتمال لحاجة الثابت إلى التغيير، مثل إعادة استخدام روتين خلط لألعاب ورق أخرى. وقد تكون مبرَّرة بالقدر نفسه باعتبارها زيادة في القدرة التعبيرية.
  • اعتبارات الأداء. قد تكون معالجة التعبير deckSize + 1 وقت التشغيل أبطأ من القيمة «53». ومع ذلك، فإن معظم المترجمات الحديثة تستخدم تقنيات مثل طيّ الثوابت وتحسين الحلقات لحلّ عملية الجمع أثناء الترجمة، لذا لا توجد عادةً عقوبة في السرعة أو تكون مهملة مقارنةً باستخدام الأرقام السحرية في الشيفرة. وعلى وجه الخصوص، يجب موازنة تكلفة التنقيح والوقت اللازم لمحاولة فهم شيفرة غير توضيحية في مقابل تكلفة الحساب الضئيلة.

الاستخدام المقبول

عندما تفتقر قيمة عددية حرفية إلى معنى خاص، فإن استخدامها لا يُصنَّف على أنه سحري، رغم أن ما يُعدّ خاصًا أمر ذاتي. ومن أمثلة القيم الحرفية التي لا تُعدّ سحرية في الغالب:

  • استخدام 0 و1 كقيمتين ابتدائيتين أو تزايديتين في حلقة for، مثل for (int i = 0; i < max; i += 1)
  • استخدام 2 للتحقق مما إذا كان رقم زوجيًا أم فرديًا، كما في isEven = (x % 2 == 0)، حيث % هو عامل باقي القسمة
  • استخدام القيم الحرفية البسيطة، مثلًا في تعابير من قبيل circumference = 2 * Math.PI * radius، أو لحساب مميِّز معادلة تربيعية على صورة d = b^2 − 4*a*c
  • استخدام قوى العدد 10 لتحويل القيم المترية (مثلًا بين الغرامات والكيلوغرامات) أو لحساب قيم النسبة المئوية والنسبة في الألف
  • الأُسُس في تعابير مثل (f(x) ** 2 + f(y) ** 2) ** 0.5 من أجل
  • تُستخدم القيمتان الحرفيتان 1 و0 أحيانًا لتمثيل القيمتين المنطقيتين true و false. ويمكن القول إن إسناد هاتين القيمتين إلى اسمين مثل TRUE وFALSE قد يكون أفضل.
  • في لغتي C وC++، كثيرًا ما يُستخدم 0 للدلالة على المؤشر الصفري رغم أن مكتبة C القياسية تعرّف ماكرو NULL وأن C++ الحديثة تتضمن الكلمة المفتاحية nullptr.

مؤشّر الصيغة

الأصل

استُخدمت مؤشّرات الصيغة لأول مرة في شيفرة يونكس الإصدار 7 المبكرة.

نُقل يونكس إلى أحد أوائل حواسيب DEC من طراز PDP-11/20، التي لم تكن تملك حماية الذاكرة. لذا استخدمت الإصدارات المبكرة من يونكس نموذج المرجع الذاكري القابل لإعادة التوضّع. كانت إصدارات يونكس السابقة لـالإصدار السادس تقرأ الملف التنفيذي إلى الذاكرة وتقفز إلى أول عنوان ذاكرة منخفض للبرنامج، أي العنوان النسبي صفر. ومع تطوير إصدارات يونكس المُصفَّحة، أُنشئت ترويسة لوصف مكوّنات الصورة التنفيذية. كما أُدرجت تعليمة تفرّع ككلمة أولى في الترويسة لتخطّي الترويسة وبدء البرنامج. وبهذه الطريقة، أمكن تشغيل البرنامج إما في نمط المرجع الذاكري القابل لإعادة التوضّع القديم (العادي) أو في النمط المُصفَّح. ومع تطوير المزيد من الصيغ التنفيذية، أُضيفت ثوابت جديدة بزيادة إزاحة التفرّع.

في الشيفرة المصدرية لـالإصدار السادس من مُحمِّل برامج يونكس، كانت الدالة exec() تقرأ الصورة التنفيذية (الثنائية) من نظام الملفات. كانت أول 8 بايتات من الملف ترويسةً تحتوي على أحجام مناطق البرنامج (النص) والبيانات (العامة) المهيأة. كذلك كانت أول كلمة بحجم 16 بت من الترويسة تُقارن بثابتين ثابتين لتحديد ما إذا كانت الصورة التنفيذية تحتوي على مراجع ذاكرية قابلة لإعادة التوضّع (عادية)، أو الصورة التنفيذية المُصفَّحة للقراءة فقط المُنفَّذة حديثًا، أو الصورة المُصفَّحة المفصولة الخاصة بالتعليمات والبيانات. ولم يُذكَر الدور المزدوج لثابت الترويسة، لكن البايت الأعلى رتبةً من الثابت كان في الواقع رمز العملية لتعليمة التفرّع في PDP-11 (ثُماني 000407 أو ست عشري 0107). وبإضافة سبعة إلى عدّاد البرنامج يتبيّن أنه إذا نُفِّذ هذا الثابت، فإنه سيُفرّع خدمة exec() في يونكس متجاوزًا ترويسة الصورة التنفيذية البالغة ثمانية بايتات ويبدأ البرنامج.

وبما أن الإصدارين السادس والسابع من يونكس استخدما شيفرة التصفيح، فقد ظلّ الدور المزدوج لثابت الترويسة مخفيًا. أي أن خدمة exec() كانت تقرأ بيانات ترويسة الملف التنفيذي (الفوقية) إلى مخزن مؤقت في فضاء النواة، لكنها كانت تقرأ الصورة التنفيذية إلى فضاء المستخدم، فلا تستخدم بذلك خاصية التفرّع للثابت. وقد نُفِّذ إنشاء الأرقام السحرية في رابط ومُحمِّل يونكس، وربما كان تفرّع الأرقام السحرية ما يزال مستخدمًا في مجموعة برامج التشخيص المستقلة التي جاءت مع الإصدارين السادس والسابع. وهكذا وفّر ثابت الترويسة وهمًا واستوفى معايير السحر.

في يونكس الإصدار السابع، لم يكن ثابت الترويسة يُختبَر مباشرةً، بل كان يُسنَد إلى متغير يحمل التسمية ux_mag ثم يُشار إليه لاحقًا بـالرقم السحري. وربما بسبب تفرّده، صار مصطلح الرقم السحري يعني نوع الصيغة التنفيذية، ثم اتسع ليعني نوع نظام الملفات، ثم اتسع مرة أخرى ليعني أي نوع من الملفات.

في الملفات

الأرقام السحرية شائعة في البرامج عبر العديد من أنظمة التشغيل. وهي تنفّذ بيانات قوية النوع وتمثّل شكلًا من الإشارات داخل النطاق الموجَّهة إلى البرنامج المتحكِّم الذي يقرأ نوع (أنواع) البيانات وقت تشغيل البرنامج. وللعديد من الملفات ثوابت من هذا القبيل تُعرّف البيانات المحتواة فيها. ويُعدّ الكشف عن مثل هذه الثوابت في الملفات وسيلة بسيطة وفعّالة للتمييز بين العديد من صيغ الملفات ويمكن أن يُنتج المزيد من المعلومات وقت التشغيل.

أمثلة
  • تبدأ ملفات أصناف جافا المترجَمة (البايت كود) وثنائيات Mach-O بالقيمة الست عشرية CA FE BA BE. وعند الضغط باستخدام Pack200 تتغير البايتات إلى CA FE D0 0D.
  • تحمل ملفات صور GIF رمز آسكي لـ"GIF89a" (47 49 46 38 39 61) أو "GIF87a" (47 49 46 38 37 61)
  • تبدأ ملفات صور JPEG بـFF D8 وتنتهي بـFF D9. وتحتوي ملفات JPEG/JFIF على السلسلة المنتهية بصفر "JFIF" (4A 46 49 46 00). وتحتوي ملفات JPEG/Exif على السلسلة المنتهية بصفر "Exif" (45 78 69 66 00)، متبوعةً بمزيد من البيانات الوصفية عن الملف.
  • تبدأ ملفات صور PNG بتوقيع من 8 بايتات يُعرّف الملف على أنه ملف PNG ويتيح كشف مشكلات نقل الملفات الشائعة: "\211PNG\r\n\032\n" (89 50 4E 47 0D 0A 1A 0A). ويحتوي ذلك التوقيع على عدة محارف سطر جديد للسماح بكشف تحويلات السطر الجديد التلقائية غير المبرَّرة، كنقل الملف باستخدام FTP بـنمط النقل آسكي بدلًا من النمط الثنائي.
  • تحمل ملفات الصوت MIDI القياسية رمز آسكي لـ"MThd" (ترويسة مسار MIDI، أي MIDI Track header، 4D 54 68 64) متبوعًا بمزيد من البيانات الوصفية.
  • قد تبدأ سكربتات يونكس أو لينكس بـشيبانغ ("#!"، 23 21) متبوعًا بمسار المفسّر، إذا كان المفسّر يُرجَّح أن يختلف عن ذلك الذي استُدعي منه السكربت.
  • تبدأ الملفات التنفيذية بصيغة ELF بالبايت 7F متبوعًا بـ"ELF" (7F 45 4C 46).
  • تبدأ ملفات بوستسكريبت وبرامجها بـ"%!" (25 21).
  • تبدأ ملفات PDF بـ"%PDF" (ست عشري 25 50 44 46).
  • تبدأ ملفات DOS MZ التنفيذية وجذع EXE لملفات PE (التنفيذية المحمولة) في مايكروسوفت ويندوز بالحرفين "MZ" (4D 5A)، وهما الأحرف الأولى من اسم مصمّم صيغة الملف، مارك زبيكوفسكي. ويسمح التعريف أيضًا بالتسلسل غير الشائع "ZM" (5A 4D) لصيغة dosZMXP، وهي ملف EXE غير PE.
  • تُعرَّف صيغة الكتلة الفائقة لـنظام بيركلي السريع للملفات إما بـ19 54 01 19 أو 01 19 54 تبعًا للإصدار؛ وكلاهما يمثّل عيد ميلاد المؤلف مارشال كيرك مكوسيك.
  • تحمل سجلّ الإقلاع الرئيسي لأجهزة التخزين القابلة للإقلاع في جميع الحواسيب المتوافقة مع IBM PC ذات معمارية IA-32 تقريبًا رمز 55 AA كآخر بايتين فيه.
  • تحمل الملفات التنفيذية لنظامي ألعاب الفيديو المحمولين Game Boy وGame Boy Advance رقمًا سحريًا بطول 48 بايت أو 156 بايت على التوالي، في موضع ثابت من الترويسة. ويُرمِّز هذا الرقم السحري خريطةً نقطية لشعار نينتندو.
  • كانت ملفات Hunk التنفيذية لبرمجيات أميغا التي تعمل على أجهزة أميغا الكلاسيكية ذات معالجات 68000 تبدأ كلها بالرقم الست عشري ‎$000003f3، المُلقَّب بـ"الكوكي السحري".
  • في أميغا، العنوان المطلق الوحيد في النظام هو الست عشري ‎$0000 0004 (موقع الذاكرة 4)، الذي يحتوي على موقع البدء المسمّى SysBase، وهو مؤشّر إلى exec.library، أي ما يُسمّى نواة أميغا.
  • تحتوي ملفات PEF، التي يستخدمها ماك أو إس الكلاسيكي وBeOS للملفات التنفيذية لمعالجات PowerPC، على رمز آسكي لـ"Joy!" (4A 6F 79 21) كبادئة.
  • تبدأ ملفات TIFF إما بـ"II" أو "MM" متبوعةً بالعدد 42 كعدد صحيح من بايتين بترتيب بايتات صغير أو كبير الطرفية. الحرفان "II" يرمزان لإنتل، التي تستخدم ترتيب البايتات صغير الطرفية، فيكون الرقم السحري 49 49 2A 00. والحرفان "MM" يرمزان لموتورولا، التي تستخدم ترتيب البايتات كبير الطرفية، فيكون الرقم السحري 4D 4D 00 2A.
  • كثيرًا ما تبدأ ملفات يونيكود النصية المُرمَّزة بـUTF-16 بـعلامة ترتيب البايتات لكشف الطرفية (FE FF للكبير الطرفية وFF FE للصغير الطرفية). وعلى مايكروسوفت ويندوز، كثيرًا ما تبدأ ملفات UTF-8 النصية بترميز UTF-8 للمحرف نفسه، EF BB BF.
  • تبدأ ملفات الشيفرة الثنائية لـLLVM بـ"BC" (42 43).
  • تبدأ ملفات WAD بـ"IWAD" أو "PWAD" (للعبة دووم)، و"WAD2" (للعبة كويك)، و"WAD3" (للعبة هاف-لايف).
  • تبدأ ملفات صيغة الملف الثنائي المركّب من مايكروسوفت (المعروفة في الغالب بأنها إحدى الصيغ الأقدم لمستندات مايكروسوفت أوفيس) بـD0 CF 11 E0، وهو ما يوحي بصريًا بكلمة "DOCFILE0".
  • كثيرًا ما تظهر الترويسات في ملفات ZIP في محرّرات النصوص على هيئة "PK♥♦" (50 4B 03 04)، حيث "PK" هما الحرفان الأولان من اسم فيل كاتس، مؤلف أداة الضغط PKZIP الخاصة بـدوس.
  • تبدأ الترويسات في ملفات 7z بـ"7z" (الرقم السحري الكامل: 37 7A BC AF 27 1C).
الكشف

يمكن لأداة يونكس file أن تقرأ الأرقام السحرية من الملفات وتفسّرها، ويُسمّى الملف المستخدم لتحليل هذه المعلومات magic. وأداة TrID في ويندوز لها غرض مماثل.

في البروتوكولات

أمثلة
  • بروتوكول OSCAR، المستخدم في AIM/ICQ، يُسبِق الطلبات بـ2A.
  • في بروتوكول RFB الذي يستخدمه VNC، يبدأ العميل محادثته مع الخادم بإرسال "RFB" (52 46 42، اختصارًا لـ"Remote Frame Buffer") متبوعًا برقم إصدار بروتوكول العميل.
  • في بروتوكول SMB الذي يستخدمه مايكروسوفت ويندوز، يبدأ كل طلب SMB أو ردّ من الخادم بـFF 53 4D 42، أو \xFFSMB في بداية طلب SMB.
  • في بروتوكول MSRPC الذي يستخدمه مايكروسوفت ويندوز، يبدأ كل طلب قائم على TCP بـ05 في بدايته (يمثّل Microsoft DCE/RPC الإصدار 5)، متبوعًا مباشرةً بـ00 أو 01 للإصدار الفرعي. أما في طلبات MSRPC القائمة على UDP فيكون البايت الأول دائمًا 04.
  • في الواجهات المُرتّبة لـCOM وDCOM، المسمّاة OBJREFs، تبدأ دائمًا بتسلسل البايتات "MEOW" (4D 45 4F 57). أما امتدادات التنقيح (المستخدمة لاعتراض قنوات DCOM) فتُسبَق بتسلسل البايتات "MARB" (4D 41 52 42).
  • تبدأ طلبات مُتعقِّب بِت تورنت غير المشفّرة ببايت واحد يحمل القيمة 19 الممثّلة لطول الترويسة، متبوعًا مباشرةً بعبارة "BitTorrent protocol" عند موضع البايت 1.
  • تبدأ حركة مرور eDonkey2000/eMule ببايت واحد يمثّل إصدار العميل. وحاليًا يمثّل E3 عميل eDonkey، ويمثّل C5 عميل eMule، ويمثّل D4 عميل eMule المضغوط.
  • تحتوي أول 4 بايتات من كتلة في سلسلة كتل بيتكوين على رقم سحري يعمل كمُعرّف للشبكة. والقيمة D9 B4 BE F9 تشير إلى الشبكة الرئيسية، بينما تشير DA B5 BF FA إلى شبكة الاختبار.
  • تبدأ معاملات SSL دائمًا برسالة "client hello". ويتكوّن مخطط تغليف السجلّات المستخدم لتسبيق جميع حزم SSL من صيغتي ترويسة بطول بايتين وثلاثة بايتات. وعادةً تُسبَق رسالة client hello في SSL الإصدار 2 بـ80، بينما يبدأ ردّ خادم SSLv3 على رسالة client hello بـ16 (رغم أن ذلك قد يتفاوت).
  • تستخدم حزم DHCP قيمة "كوكي سحري" تساوي 63 82 53 63 في بداية قسم الخيارات من الحزمة. وتُدرَج هذه القيمة في جميع أنواع حزم DHCP.
  • تبدأ اتصالات HTTP/2 بالسلسلة المكوّنة من 24 محرفًا PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n. وهي مصمَّمة لتفادي معالجة الإطارات من قِبل الخوادم والوسطاء الذين يدعمون إصدارات HTTP الأقدم دون الإصدار 2.0.
  • يستخدم مصافحة فتح WebSocket سلسلةً تحتوي على UUIDv4 258EAFA5-E914-47DA-95CA-C5AB0DC85B11.

في الواجهات

الأرقام السحرية شائعة في دوال واجهات برمجة التطبيقات والواجهات عبر العديد من أنظمة التشغيل، بما في ذلك دوس وويندوز ونِت وير:

أمثلة
  • تستخدم أنظمة BIOS المتوافقة مع IBM PC القيمتين السحريتين 00 00 و12 34 لتقرير ما إذا كان على النظام أن يعدّ الذاكرة أم لا عند إعادة التشغيل، فيؤدي بذلك إقلاعًا باردًا أو دافئًا. وتستخدم مديرات الذاكرة EMM386 هاتين القيمتين أيضًا عند اعتراض طلبات الإقلاع. كما تستخدم أنظمة BIOS القيمة السحرية 55 AA لتحديد ما إذا كان القرص قابلًا للإقلاع.
  • تستخدم ذاكرة التخزين المؤقت للأقراص في MS-DOS المسمّاة SMARTDRV (واسمها الرمزي "Bambi") القيمتين السحريتين BA BE وEB AB في دوال واجهة برمجة التطبيقات.
  • تستخدم العديد من مشغّلات DR-DOS وNovell DOS وOpenDOS التي طُوِّرت في مركز التطوير الأوروبي السابق في المملكة المتحدة القيمة 0E DC كرمز سحري عند استدعاء أو توفير وظائف إضافية تعمل فوق دوال دوس القياسية (المُحاكاة)، وNWCACHE أحد الأمثلة على ذلك.

استخدامات أخرى

أمثلة
  • عنوان MAC الافتراضي على شرائح SOC من تكساس إنسترومنتس هو DE:AD:BE:EF:00:00.

GUID

من الممكن إنشاء أو تعديل المُعرّفات الفريدة عالميًا (GUIDs) لتكون سهلة التذكّر، لكن لا يُنصَح بذلك مطلقًا لأنه يضعف قوّتها كمُعرّفات شبه فريدة. فمواصفات توليد المُعرّفات GUID وUUID معقّدة للغاية، وهو ما يجعلها فريدة فعليًا إذا نُفِّذت تنفيذًا صحيحًا.

أحيانًا تنتهي أرقام مُعرّف المنتج في مايكروسوفت ويندوز لمنتجات مايكروسوفت أوفيس بـ0000-0000-0000000FF1CE ("OFFICE")، مثل 90160000-008C-0000-0000-0000000FF1CE، وهو مُعرّف المنتج لـ"مكوّن قابلية التوسعة Office 16 Click-to-Run".

تستخدم جافا عدة مُعرّفات GUID تبدأ بـCAFEEFAC.

في جدول أقسام GUID لمخطط التقسيم GPT، تستخدم أقسام إقلاع BIOS المُعرّف الخاص 21686148-6449-6E6F-744E-656564454649 الذي لا يتبع تعريف GUID؛ بل يتكوّن باستخدام رموز آسكي للسلسلة Hah!IdontNeedEFI جزئيًا بترتيب صغير الطرفية.

قيمة التنقيح

الـقيم السحرية للتنقيح هي قيم محددة تُكتب إلى الذاكرة أثناء التخصيص أو إلغاء التخصيص، بحيث يصبح من الممكن لاحقًا معرفة ما إذا كانت قد تلِفت أم لا، وجعل استخدام قيم مأخوذة من ذاكرة غير مهيأة أمرًا واضحًا. وعادةً ما يُنظر إلى الذاكرة بالنظام الست عشري، لذا تشيع القيم المتكررة سهلة التذكّر أو قيم الهكسبيك. وقد يُفضَّل اختيار قيم فردية عدديًا حتى تُخفِق المعالجات التي لا تملك عنونة بايتية عند محاولة استخدامها كمؤشّرات (التي يجب أن تقع عند عناوين زوجية). وينبغي اختيار قيم تبتعد عن العناوين المحتملة (شيفرة البرنامج، أو البيانات الساكنة، أو بيانات الكومة، أو المكدس). وبالمثل، قد تُختار بحيث لا تكون رموزًا صالحة في مجموعة تعليمات المعمارية المعنية.

وبما أنه من غير المرجّح للغاية، وإن كان ممكنًا، أن يأخذ عدد صحيح بحجم 32 بت هذه القيمة المحددة، فإن ظهور مثل هذا الرقم في مُنقِّح أو تفريغ ذاكرة يشير على الأرجح إلى خطأ مثل تجاوز سعة المخزن المؤقت أو متغير غير مهيأ.

تشمل الأمثلة المشهورة والشائعة ما يلي:

الرمز الوصف
00008123 يُستخدم في MS Visual C++. تُضبط المؤشّرات المحذوفة على هذه القيمة بحيث تُطلِق استثناءً عند استخدامها لاحقًا؛ وهي اسم بديل أكثر قابلية للتمييز للعنوان الصفري. ويُفعَّل عبر خيار دورة حياة التطوير الآمن (/sdl).
..FACADE "Facade"، تستخدمه عدة أنظمة تشغيل آنية.
1BADB002 "1 bad boot"، الرقم السحري لترويسة Multiboot.
8BADF00D "Ate bad food"، يشير إلى أن تطبيق iOS من آبل قد أُنهي بسبب انتهاء مهلة المراقِب (watchdog).
A5A5A5A5 يُستخدم في تطوير الأنظمة المضمَّنة لأن نمط البتات المتناوب (1010 0101) يُنتج نمطًا سهل التمييز على راسمات الذبذبات ومحلّلات المنطق.
A5 يُستخدم في دالة malloc(3) من نوع PHK في FreeBSD للتنقيح عندما يكون ‎/etc/malloc.conf مرتبطًا رمزيًا بـ"-J" لتهيئة كل ذاكرة مخصَّصة حديثًا، إذ إن هذه القيمة ليست مؤشّرًا صفريًا ولا محرف NUL في آسكي.
ABABABAB تستخدمه دالة HeapAlloc() التنقيحية من مايكروسوفت لتعليم بايتات الحراسة في "الأرض الحرام" بعد ذاكرة الكومة المخصَّصة.
ABADBABE "A bad babe"، تستخدمه آبل كرقم سحري لـ"Boot Zero Block".
ABBABABE "ABBA babe"، تستخدمه كومة ذاكرة لعبة Driver: Parallel Lines.
ABADCAFE "A bad cafe"، تُستخدم لتهيئة كل الذاكرة غير المخصَّصة (Mungwall، AmigaOS).
B16B00B5 "Big Boobs"، كانت مايكروسوفت تتطلّب سابقًا من ضيوف لينكس استخدامها في مُراقِب Hyper-V كالنصف الأعلى من "مُعرّف الضيف" الخاص بهم.
BAADF00D "Bad food"، تستخدمه دالة HeapAlloc() التنقيحية من مايكروسوفت لتعليم ذاكرة الكومة المخصَّصة غير المهيأة.
BAAAAAAD "Baaaaaad"، يشير إلى أن سجلّ iOS من آبل هو لقطة مكدس للنظام بأكمله، وليس تقرير تعطّل.
BAD22222 "Bad too repeatedly"، يشير إلى أن تطبيق صوت عبر الإنترنت (VoIP) على iOS من آبل قد أُنهي لأنه استُؤنف بتكرار مفرط.
BADBADBADBAD "Bad bad bad bad"، ذاكرة "غير مهيأة" في أنظمة بوروز الكبيرة (كلمات بطول 48 بت).
BADC0FFEE0DDF00D "Bad coffee odd food"، تُستخدم على أنظمة RS/6000 ذات 64 بت من IBM للإشارة إلى مسجّلات المعالج غير المهيأة.
BADDCAFE "Bad cafe"، على نظام سولاريس من صن مايكروسيستمز، تُعلّم ذاكرة النواة غير المهيأة (KMEM_UNINITIALIZED_PATTERN).
BBADBEEF "Bad beef"، تُستخدم في WebKit للأخطاء التي يتعذّر التعافي منها على وجه الخصوص.
BEBEBEBE تستخدمه AddressSanitizer لملء الذاكرة المخصَّصة لكن غير المهيأة.
BEEFCACE "Beef cake"، تستخدمه مايكروسوفت .NET كرقم سحري في ملفات الموارد.
C00010FF "Cool off"، يشير إلى أن نظام التشغيل أوقف تطبيق iOS من آبل استجابةً لحدث حراري.
CAFEBABE "Cafe babe"، تستخدمه جافا لملفات الأصناف.

تُستخدم في ثنائيات Mach-O متعددة المعماريات.

CAFED00D "Cafe dude"، تستخدمه جافا لضغط pack200 الخاص بها.
CAFEFEED "Cafe feed"، تستخدمه نواة التنقيح في نظام سولاريس من صن مايكروسيستمز لتعليم ذاكرة kmemfree().
CCCCCCCC تستخدمه مكتبة وقت تشغيل تنقيح C++ من مايكروسوفت والعديد من بيئات دوس لتعليم ذاكرة المكدس غير المهيأة. والقيمة CC هي رمز عملية مقاطعة نقطة توقف التنقيح INT 3 على معالجات x86.
CDCDCDCD تستخدمه دالة malloc() التنقيحية لـ C/C++ من مايكروسوفت لتعليم ذاكرة الكومة غير المهيأة، التي تُعاد عادةً من HeapAlloc.
0D15EA5E "Zero Disease"، تُستخدم كرَاية للإشارة إلى الإقلاع العادي على جهازي غيم كيوب ووي.
DDDDDDDD تستخدمه SmartHeap من MicroQuill ودالة free() التنقيحية لـ C/C++ من مايكروسوفت لتعليم ذاكرة الكومة المُحرَّرة.
DEAD10CC "Dead lock"، يشير إلى أن تطبيق iOS من آبل قد أُنهي لأنه ظلّ ممسكًا بمورد من موارد النظام أثناء عمله في الخلفية.
DEADBABE "Dead babe"، تُستخدم في بداية ملفات arena الخاصة بنظام IRIX من سيليكون غرافيكس.
DEADBEEF "Dead beef"، اشتهرت باستخدامها على أنظمة IBM مثل RS/6000، كما تُستخدم في أنظمة تشغيل ماك أو إس الكلاسيكي، وOPENSTEP Enterprise، وأميغا من كومودور. وعلى نظام سولاريس من صن مايكروسيستمز، تُعلّم ذاكرة النواة المُحرَّرة (KMEM_FREE_PATTERN).
DEADCAFE "Dead cafe"، تستخدمه مايكروسوفت .NET كرقم خطأ في مكتبات الربط الديناميكي (DLLs).
DEADC0DE "Dead code"، تُستخدم كعلامة في البرنامج الثابت لـOpenWRT للدلالة على بداية نظام ملفات jffs2 المراد إنشاؤه في نهاية البرنامج الثابت الساكن.
DEADFA11 "Dead fail"، يشير إلى أن المستخدم قد أغلق تطبيق iOS من آبل قسرًا.
DEADF00D "Dead food"، تستخدمها Mungwall على أميغا من كومودور لتعليم الذاكرة المخصَّصة لكن غير المهيأة.
DEFEC8ED "Defecated"، تُستخدم في تفريغات ذاكرة core لنظام OpenSolaris.
DEADDEAD "Dead Dead" يشير إلى أن المستخدم بدأ عمدًا تفريغ تعطّل إما من مُنقِّح النواة أو من لوحة المفاتيح في مايكروسوفت ويندوز.
D00D2BAD "Dude, Too Bad"، تستخدمها تعطّلات Safari على macOS Big Sur.
D00DF33D "Dude feed"، تستخدمها شجرة الأجهزة لتعليم بداية الترويسات.
EBEBEBEB من SmartHeap من MicroQuill.
FADEDEAD "Fade dead"، تأتي في النهاية لتعريف كل سكربت AppleScript.
FDFDFDFD تستخدمه دالة malloc() التنقيحية لـ C/C++ من مايكروسوفت لتعليم بايتات الحراسة في "الأرض الحرام" قبل ذاكرة الكومة المخصَّصة وبعدها، وكذلك بعض دوال C-Runtime الآمنة التنقيحية التي تنفّذها مايكروسوفت (مثل strncat_s).
FEE1DEAD "Feel dead"، يستخدمها استدعاء النظام reboot() في لينكس.
FEEDFACE "Feed face"، تُشاهَد في ثنائيات Mach-O على منصة Mac OSX من آبل. وعلى نظام سولاريس من صن مايكروسيستمز، تُعلّم المنطقة الحمراء (KMEM_REDZONE_PATTERN).

تستخدمها مشغّل VLC وبعض كاميرات IP في بروتوكول RTP/RTCP، حيث يرسل مشغّل VLC أربعة بايتات بترتيب طرفية النظام. وتتوقّع بعض كاميرات IP أن يرسل المشغّل هذا الرقم السحري ولا تبدأ البث إن لم تستلمه.

FEEEFEEE "Fee fee"، تستخدمه دالة HeapFree() التنقيحية من مايكروسوفت لتعليم ذاكرة الكومة المُحرَّرة. وقد تحمل بعض قيم مسك الدفاتر الداخلية القريبة الكلمة العليا مضبوطة على FEEE أيضًا.

معظم هذه القيم بطول 32 بت – وهو حجم الكلمة في معظم الحواسيب ذات معمارية 32 بت.

إن شيوع هذه القيم في تقنيات مايكروسوفت ليس من قبيل الصدفة؛ فقد نوقشت بالتفصيل في كتاب ستيف ماغواير Writing Solid Code الصادر عن مايكروسوفت بريس. وهو يقدّم مجموعة متنوعة من المعايير لهذه القيم، مثل:

  • ينبغي ألا تكون مفيدة؛ أي أن يُتوقَّع من معظم الخوارزميات التي تعمل عليها أن تفعل شيئًا غير اعتيادي. والأرقام مثل الصفر لا تستوفي هذا المعيار.
  • ينبغي أن يتعرّف المبرمج عليها بسهولة بوصفها قيمًا غير صالحة في المُنقِّح.
  • على الأجهزة التي لا تملك محاذاة بايتية، ينبغي أن تكون أعدادًا فردية، بحيث يؤدي اعتبارها عناوين والإحالة إليها إلى استثناء.
  • ينبغي أن تسبّب استثناءً، أو ربما حتى توقّف المُنقِّح، إذا نُفِّذت كشيفرة.

وبما أنها كثيرًا ما استُخدمت لتعليم مناطق من الذاكرة كانت فارغة في جوهرها، فقد صار بعض هذه المصطلحات يُستخدم في عبارات تعني "ذهب، أُجهض، طُرد من الذاكرة"؛ مثل "برنامجك صار DEADBEEF".