حين تكسب مكتبة Delphi إعداد بناء دون الإطار المرئي، تصبح الأصناف البديلة موطن الأخطاء. لا المنصة ولا المترجم: البدائل. فـ PDFlibPas تملك طبقة رسوميات توفر مكافئات لـ bitmap وcanvas وخط وملف تعريفي وطابعة للبناءات دون VCL، ونقلها إلى Free Pascal أظهر كل نمط إخفاق يمكن أن تمر به البديلة. وهي تترتب بترتيب أنيق حسب كلفة التشخيص، والترتيب معاكس لما توحي به الحدس
البديلة التي ترمي استثناء رخيصة الاكتشاف؛ فالاستثناء يسمي التابع. والبديلة التي تعيد بيانات فارغة مكلفة، لأن الإخفاق يظهر بعدة طبقات عن سببه. والبديلة التي تفيد بالنجاح هي أسوأ الجميع، لأن رمز الإرجاع صالح، ورمز الخطأ صفر، ولا استثناء يُرمى، والدليل الوحيد على خلل ما في البايتات التي خرجت
الهيئة الثالثة: معرّف صورة صالح فوق XObject فارغ
كان محول الملف التعريفي المتجهي جسم تابع فارغا في إعداد non-VCL. وكل ما فوقه ظل يعمل. نقاط دخول استيراد EMF ونقطة دخول التقاط لوحة الرسم أكملت دورتها وأعادت معرف صورة قانونيا، وضعه المستدع على صفحة. وما استقر في الملف كان form XObject بطول محتوى صفر. ورُسمت الصفحة بيضاء
لم يفد أحد عن مشكلة، ويشمل ذلك برنامج العرض التوضيحي الخاص بالمكتبة لهذه الميزة، الذي رسم صفحة فارغة ولم ينتبه. لم تكن هناك قيمة إرجاع فاشلة لفحصها، لأن تسلسل النداءات نجح كل نجاح حقيقي؛ والشيء الوحيد الخاطئ كان حجم المسار المنتج. تشخيص هذا الصنف من العيوب يعني طرح سؤال مختلف: ليس «هل فشل النداء» بل «هل الأثر معقول». فـ form XObject بطول صفر، وصورة بعدد بكسلات صفر، وصفحة بمحتوى بايتات صفر، هذه هي التوكيدات التي تلتقطه
للإصلاح نصفان والنصف الثاني سهل النسيان. أولا اجعل التنفيذ الفارغ يرمي، كي يكون للإخفاق قناة أصلا. ثانيا حوّل ذلك الاستثناء إلى نتيجة معدومة في مصنع الصور وأضف فحوص العدم في الموضعين المستهلكين لمعرف صورة، لأن «الإخفاق النظيف» وإلا يتحول مباشرة إلى مخالفة وصول عندما يلغي شجرة الصفحات إلغاء مرجعية لعدم شيء. والـ stub الذي يرمي ليس تحسينا إلا إذا كان المستدعون مستعدين لإخفاق لم يكونوا قادرين على استلامه من قبل
الهيئة الثانية: بيانات فارغة على بعد ثلاث طبقات من الانهيار
البديلة للوحة رسم الملف التعريفي لم تملأ أبعادها الفيزيائية. تلك القيمة تدخل قسمة في حساب هندسة صفحة، فأنتج الحساب صفرا، فقسم حساب الصندوق المحيط على صفر. ابتلع معالج استثناء عار ذلك، وأعاد مصنع الصور نتيجة معدومة، وحدثت مخالفة الوصول أخيرا في شجرة الصفحات عند استخدام العدم. ثلاث طبقات بين السبب والعرض، ومعالج استثناء في المنتصف يمحو الدليل
كانت في الوحدة نفسها حالتان إضافيتان للنمط. صنف الخط كان بجسمي Assign وبانٍ فارغين، وهو ما يهم أكثر مما يبدو لأن خاصية الخط في لوحة الرسم للقراءة فقط: الإسناد إليها هو الطريق الوحيد لتسليم خط، فيجعل التنفيذ الفارغ اختيار الخط غير فعال بصمت ويخرج النص بأي خط كان الافتراضي. وقيمة بكسل لكل بوصة تساوي صفرا جعلت كل مستدع يضبط لوحة رسم من مقاييس الخط ينتج لوحة صفر في صفر، بما يعطي صفحة فارغة وإرجاع نجاح
// الشكل الذي تبحث عنه في وحدة بديلة: تابع لا يرمي استثناء
// ولا يفعل شيئا. كلاهما يترجم وكلاهما
// ينتج «نجاحا» بلا مخرجات
procedure TMetafileCanvasStandIn.Create(...);
begin
// بلا نداء وراثي ولا تهيئة حقول
end;
function TBitmapStandIn.LoadFromStream(Stream: TStream): Boolean;
begin
Result := True; // والصورة النقطية ما تزال فارغة
end;
البنية الواسعة التي تحتفظ بالحرف الأول فقط
هذه ليست مشكلة بديلة إطلاقا، لكنها تنتمي إلى الفهرس نفسه لأن العرض يبعد عن السبب بالمقدار نفسه. صُرّحت بنية تعداد الطابعات بكل أعضائها الاثني عشر النصية كمؤشرات إلى محارف أحادية البايت، بينما الدالة التي تملؤها هي الصيغة ذات المحارف الواسعة من واجهة التعداد
أحجام المؤشرات متطابقة، فتخطيط البنية صحيح ولا شيء ينهار. ما يحدث بدلا من ذلك أن قراءة سلسلة UTF-16 كسلسلة أحادية البايت تتوقف عند أول بايت معدوم، وهو لأي اسم طابعة ASCII النصف الأعلى من الحرف الثاني. وعاد كل اسم طابعة بحرف واحد بالضبط. وفي اتجاه المصب، فشل التحقق من الاسم، وفشل إنشاء الطابعة، وفشلت الطباعة لكل طابعة حقيقية على الجهاز، ولا شيء من تلك الأعراض يشير إلى إعلان بنية
// خاطئ: الحجم صحيح ونوع العنصر خاطئ. لا خطأ ترجمة ولا انهيار،
// وكل سلسلة مقصوصة إلى حرف واحد
type
TPrinterInfo2Wrong = record
pServerName: PAnsiChar;
pPrinterName: PAnsiChar;
// ... وعشرة أخرى
end;
// صحيح: بنية *W أعضاؤها واسعة في كل حقولها
type
TPrinterInfo2W = record
pServerName: PWideChar;
pPrinterName: PWideChar;
// ... وعشرة أخرى
end;
القاعدة المستخلصة ميكانيكية وتستحق التطبيق دون تفكير: لأي بنية Win32 ينتهي اسمها بـ W، تحقق أن كل عضو نصي هو الصيغة الواسعة، حقلا بحقل. ومزج عالمي ANSI والواسع لا ينتج تشخيص مترجم ولا انهيارا، بل قصا صامتا فقط، وينطبق الأمر نفسه بالعكس على صيغ ANSI
معالج الاستثناء العار هو الخصم الحقيقي
أبطأت كل تحققات تلك البنية نفسها: معالج يلتقط كل شيء ويحوله إلى قيمة إرجاع خاطئة. وهو أمر معقول الكتابة حول فاك ترميز صور، إذ لا ينبغي لصورة تالفة أن تُسقط مهمة مستند. وهو أيضا أداة لحذف قطعة المعلومة الوحيدة التي تحتاجها
الاستجابة العملية هي جعل المعالج صاخبا مؤقتا. تفريغ صنف الاستثناء ورسالته وأثر الرجوع من داخل المعالج العار، تحت شرط تجميعي للتنقيح، يحول إرجاعا معدوما غير مفسّر إلى استثناء مسمى بموضع. وفي حالتين من الحالات الثلاث أعلاه أنهت تلك الخطوة الواحدة التحقيق، لأن الاستثناء كان قسمة على صفر أو مخالفة وصول في تابع بديلة قال اسمه كل شيء
قائمة فحص لتبني مسار بديلة
أربعة بنود، بالترتيب الذي يؤتي ثماره. قبل النداء إلى صنف بديل، اقرأ التوابع التي سوف تستخدمها وتأكد أن لكل منها جسما حقيقيا؛ فالجسم الفارغ ليس تفصيل تنفيذ بل ميزة مفقودة. فضّل البدائل الرامية لاستثناء على البدائل العائدة بقيم محايدة، واقرن ذلك بفحوص العدم في المواضع التي يمكن لمصنع أن يعيد فيها العدم بشكل مشروع الآن. تحقق من ميزة بفحص الأثر لا رمز الإرجاع، لأن نمط الإخفاق كله هنا رمز إرجاع نظيف فوق أثر فارغ؛ والتفصيل على مستوى البايت لما يحويه المستند فعلا هو أسرع طريقة لرؤيته، ومقال تدقيق حجم الملف يغطي تلك الأدوات. وعندما لا توجد لميزة تنفيذ بديل قابل للحياة، وجّه العينات المتأثرة إلى المسار الذي يعمل وقل السبب في تعليق، بدل ترك عرض توضيحي ينتج بهدوء مخرجات فارغة
النقطة الأوسع تنطبق إلى ما وراء مكتبة واحدة. أي قاعدة كود لها تنفيذ ثان شرطي، أو طبقة محاكاة، أو وضع بلا واجهة، أو رافعة منصات، معرضة للهيئة الثالثة. وسبب إخفائها بهذا الإتقان أن كل بوابة جودة يعتمد عليها الفريق عادة، رموز إرجاع ورموز خطأ واستثناءات وحالات خروج، قناة حالة، والهيئة الثالثة تبقيها جميعا نظيفة. والمخرجات وحدها التي تفضحه. وهذا هو الاستدلال نفسه وراء فحص الأثر لا الحالة عند معالجة مدخلات غير موثوقة، الموصوف في مقال تحليل PDF غير الموثوق، ووراء مقارنة المخرجات المصيرة عبر المحركات بدل الوثوق بواحد، الموصوف في التصيير متعدد المحركات
PDFlibPas مكتبة PDF أصيلة بلغة Object Pascal لكل من Delphi وC++Builder وFree Pascal، وإعدادها غير VCL هو ما يجعل البناءات بلا واجهة وعبر سلاسل الأدوات ممكنة؛ وتغطية الإعدادات الحالية مدرجة في صفحة منتج losLab PDF Developer Library