أمان النوع

في علوم الحاسوب ، يُقصد بأمان النوع مدى قدرة لغة البرمجة على الحد من أخطاء النوع أو منعها . وتُسمى اللغات الآمنة من حيث النوع أحيانًا باللغات ذات النوع القوي أو الصارم . أما السلوكيات التي تُصنف على أنها أخطاء نوع في لغة برمجة معينة، فهي عادةً تلك الناتجة عن محاولات إجراء عمليات على قيم ليست من نوع البيانات المناسب ، مثل محاولة جمع سلسلة نصية مع عدد صحيح .

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

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

التعريفات

بشكل بديهي، يمكن تلخيص سلامة النوع في عبارة روبن ميلنر الموجزة التي تقول

البرامج المكتوبة بشكل جيد لا يمكن أن "تخطئ". [ 2 ]

بمعنى آخر، إذا كان نظام الأنواع سليمًا ، فإن التعبيرات التي يقبلها هذا النظام يجب أن تُقيّم إلى قيمة من النوع المناسب (بدلاً من إنتاج قيمة من نوع آخر غير ذي صلة أو التسبب في خطأ في النوع). يقدم فيجاي ساراسوات التعريف التالي ذي الصلة:

تكون اللغة آمنة من حيث النوع إذا كانت العمليات الوحيدة التي يمكن إجراؤها على البيانات في اللغة هي تلك المسموح بها من قبل نوع البيانات. [ 3 ]

مع ذلك، فإنّ ما يعنيه تحديدًا أن يكون البرنامج "مُصنَّفًا بشكل صحيح" أو أن "يحدث به خلل" يعتمد على خصائص دلالاته الثابتة والديناميكية ، وهي خصائص خاصة بكل لغة برمجة. وبالتالي، فإنّ التعريف الرسمي الدقيق لسلامة النوع يعتمد على أسلوب الدلالات الرسمية المُستخدمة لتحديد اللغة. في عام ١٩٩٤، صاغ أندرو رايت وماتياس فيليسين ما أصبح التعريف القياسي وتقنية إثبات سلامة النوع في اللغات المُعرَّفة بدلالات تشغيلية ، [ ٤ ] وهو الأقرب إلى مفهوم سلامة النوع كما يفهمه معظم المبرمجين. وفقًا لهذا النهج، يجب أن تتوافر في دلالات اللغة الخاصيتان التاليتان لتُعتبر سليمة النوع:

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

كما نُشر عدد من المعالجات الرسمية الأخرى لسلامة النوع من حيث الدلالات الدلالية والدلالات التشغيلية البنيوية . [ 2 ] [ 5 ] [ 6 ]

العلاقة بأشكال السلامة الأخرى

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

اللغات الآمنة من حيث النوع واللغات غير الآمنة من حيث النوع

عادةً ما يُعدّ أمان النوع شرطًا أساسيًا لأي لغة برمجة تجريبية (أي لغة متخصصة ) تُقترح في أبحاث لغات البرمجة الأكاديمية. مع ذلك، فإن العديد من اللغات أكبر من أن تُبرهن عليها البشر يدويًا، إذ غالبًا ما تتطلب فحص آلاف الحالات. ومع ذلك، فقد ثبت أن بعض اللغات، مثل Standard ML ، التي تتميز بدلالات محددة بدقة، تُلبي أحد تعريفات أمان النوع. [ 8 ] ويُعتقد أن بعض اللغات الأخرى، مثل Haskell، تُلبي تعريفًا ما لأمان النوع، شريطة عدم استخدام بعض ميزات "الهروب" (على سبيل المثال، دالة unsafePerformIO في Haskell ، المستخدمة "للهروب" من البيئة المقيدة المعتادة التي تسمح بالإدخال/الإخراج ، تتجاوز نظام النوع، وبالتالي يمكن استخدامها لخرق أمان النوع. [ 9 ] ). يُعدّ التلاعب بالأنواع مثالًا آخر على ميزة "الهروب" هذه. بغض النظر عن خصائص تعريف اللغة، قد تحدث بعض الأخطاء أثناء التشغيل بسبب أخطاء في التنفيذ، أو في المكتبات المرتبطة المكتوبة بلغات أخرى؛ وقد تجعل هذه الأخطاء نوع تنفيذ معين غير آمن في ظروف معينة. كانت إحدى النسخ المبكرة من آلة جافا الافتراضية من صن عرضة لهذا النوع من المشاكل. [ 3 ]

الكتابة القوية والضعيفة

غالبًا ما تُصنَّف لغات البرمجة، بشكلٍ عام، إلى لغات ذات أنواع بيانات قوية أو لغات ذات أنواع بيانات ضعيفة (أو ذات أنواع بيانات غير دقيقة) للإشارة إلى جوانب معينة من سلامة أنواع البيانات. في عام 1974، عرّف ليسكوف وزيلز اللغة ذات أنواع البيانات القوية بأنها اللغة التي "عند تمرير أي كائن من دالة مُستدعِية إلى دالة مُستدعاة، يجب أن يكون نوعه متوافقًا مع النوع المُعلن عنه في الدالة المُستدعاة". [ 10 ] وفي عام 1977، كتب جاكسون: "في اللغة ذات أنواع البيانات القوية، يكون لكل منطقة بيانات نوع بيانات مميز، وتُحدد كل عملية متطلبات الاتصال الخاصة بها بدلالة هذه الأنواع". [ 11 ] في المقابل، قد تُنتج اللغة ذات أنواع البيانات الضعيفة نتائج غير متوقعة أو قد تُجري تحويلًا ضمنيًا لأنواع البيانات. [ 12 ]

إدارة الذاكرة وسلامة الأنواع

يرتبط أمان النوع ارتباطًا وثيقًا بأمان الذاكرة . على سبيل المثال، في تطبيق لغة تحتوي على نوع معينت{\displaystyle t}يسمح هذا ببعض أنماط البتات دون غيرها، ويسمح خطأ في ذاكرة المؤشر المعلق بكتابة نمط بتات لا يمثل عضوًا شرعيًا منت{\displaystyle t}إلى متغير ميت من النوعت{\displaystyle t}مما يتسبب في حدوث خطأ في النوع عند قراءة المتغير. وعلى العكس من ذلك، إذا كانت اللغة آمنة من حيث الذاكرة، فلا يمكنها السماح باستخدام عدد صحيح عشوائي كمؤشر ، وبالتالي يجب أن يكون هناك نوع مؤشر أو مرجع منفصل.

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

تستخدم معظم لغات البرمجة الآمنة من حيث النوع آلية جمع البيانات المهملة . يقول بيرس: "من الصعب للغاية تحقيق أمان النوع في وجود عملية تحرير صريحة للذاكرة"، وذلك بسبب مشكلة المؤشر المعلق. [ 13 ] ومع ذلك، تُعتبر لغة Rust آمنة من حيث النوع بشكل عام، وتستخدم مدقق الاستعارة لتحقيق أمان الذاكرة، بدلاً من جمع البيانات المهملة.

أمان النوع في لغات البرمجة الكائنية

في لغات البرمجة الكائنية التوجه، عادةً ما يكون أمان النوع متأصلاً في وجود نظام أنواع . ويتم التعبير عن ذلك من خلال تعريفات الفئات.

يُعرّف الصنف أساسًا بنية الكائنات المشتقة منه، وتُعرّف واجهة برمجة التطبيقات (API) بمثابة عقد للتعامل مع هذه الكائنات. في كل مرة يتم فيها إنشاء كائن جديد، فإنه يلتزم بهذا العقد.

كل دالة تتبادل كائنات مشتقة من فئة معينة، أو تُنفذ واجهة معينة ، ستلتزم بهذا العقد: وبالتالي، فإن العمليات المسموح بها في تلك الدالة على ذلك الكائن ستكون فقط تلك المُعرَّفة بواسطة أساليب الفئة التي يُنفذها الكائن. وهذا سيضمن الحفاظ على سلامة الكائن. [ 14 ]

الاستثناءات من ذلك هي لغات البرمجة الكائنية التي تسمح بالتعديل الديناميكي لبنية الكائن، أو استخدام الانعكاس لتعديل محتوى الكائن للتغلب على القيود التي تفرضها تعريفات أساليب الفئة.

مشاكل أمان الكتابة في لغات محددة

آدا

صُممت لغة آدا لتكون مناسبة للأنظمة المدمجة ، وبرامج تشغيل الأجهزة ، وأنواع أخرى من برمجة الأنظمة ، ولتشجيع البرمجة الآمنة من حيث أنواع البيانات. ولحل هذه المعضلة، تحصر آدا عدم أمان أنواع البيانات في مجموعة محددة من البنى الخاصة التي تبدأ أسماؤها عادةً بالسلسلة Unchecked_ . ويمكن منع Unchecked_Deallocation فعليًا من وحدة نصية في آدا بتطبيق pragma Pure على هذه الوحدة. ومن المتوقع أن يستخدم المبرمجون بنى Unchecked_ بحذر شديد وعند الضرورة فقط؛ فالبرامج التي لا تستخدمها تكون آمنة من حيث أنواع البيانات.

لغة البرمجة SPARK هي مجموعة فرعية من لغة Ada، تتخلص من جميع أوجه الغموض وعدم الأمان المحتملة فيها، مع إضافة ميزة التحقق الثابت من العقود إلى ميزات اللغة المتاحة. تتجنب SPARK مشاكل المؤشرات المعلقة بمنع تخصيص الذاكرة أثناء التشغيل تمامًا.

تضيف Ada2012 عقودًا يتم التحقق منها بشكل ثابت إلى اللغة نفسها (في شكل شروط مسبقة ولاحقة، بالإضافة إلى ثوابت النوع).

ج

لغة البرمجة C آمنة من ناحية أنواع البيانات في سياقات محدودة؛ فعلى سبيل المثال، يُولّد خطأ أثناء الترجمة عند محاولة تحويل مؤشر إلى نوع بنية بيانات معين إلى مؤشر إلى نوع بنية بيانات آخر، ما لم يُستخدم تحويل صريح. مع ذلك، فإن عددًا من العمليات الشائعة جدًا غير آمنة من ناحية أنواع البيانات؛ فعلى سبيل المثال، الطريقة المعتادة لطباعة عدد صحيح هي كالتالي: printf('printf') = printf('printf') = printf('printf') />، printf("%d", 12)حيث %dيُخبر printf printfوقت التشغيل أن الدالة تتوقع وسيطًا من نوع عدد صحيح. ( printf("%s", 12)قد تقبل المترجمات طريقة أخرى مثل printf('printf') = printf('printf') = printf('printf') />، والتي تُخبر الدالة أن تتوقع مؤشرًا إلى سلسلة نصية مع تمرير وسيط من نوع عدد صحيح، ولكنها ستُنتج نتائج غير مُعرّفة). يتم التخفيف من هذا جزئيًا من خلال قيام بعض المترجمات (مثل gcc) بفحص تطابق أنواع البيانات بين وسائط printf وسلاسل التنسيق.

بالإضافة إلى ذلك، توفر لغة C، مثل لغة Ada، تحويلات صريحة غير محددة أو غير مُعرَّفة؛ وعلى عكس لغة Ada، فإنّ الأساليب التي تستخدم هذه التحويلات شائعة جدًا، وقد ساهمت في إعطاء لغة C سمعة بأنها غير آمنة من حيث أنواع البيانات. على سبيل المثال، الطريقة القياسية لتخصيص الذاكرة في الكومة هي استدعاء دالة تخصيص الذاكرة، مثل `foo()` malloc، مع وسيط يُشير إلى عدد البايتات المطلوبة. تُعيد هذه الدالة مؤشرًا فارغًا (` void`)، والذي يجب على الكود المُستدعي تحويله صراحةً أو ضمنيًا إلى نوع المؤشر المناسب. كانت التطبيقات السابقة للغة C تتطلب تحويلًا صريحًا للقيام بذلك، ولذلك أصبح الكود المُستخدم void*لتخصيص بعض البيانات هو الممارسة المقبولة. [ 15 ] تُعيد `void ()`، وهو ما لا يحتاج إلى تحويل صريح في لغة C، ولكن في لغة C++، أصبح هذا التحويل إلزاميًا لضمان سلامة أنواع البيانات.struct FooFoo* foo = (struct Foo*)malloc(sizeof(struct Foo))malloc()void*

لغة سي++

تعتبر لغة C++ بشكل عام أكثر أمانًا من حيث النوع من سابقتها، لغة C، وذلك بفضل ميزات مثل عدم السماح بالتحويل الضمني من void*نوع مؤشر إلى نوع مؤشر آخر [ 16 ] وميزات أخرى مثل:

سي شارب

لغة C# آمنة من حيث أنواع البيانات. تدعم المؤشرات غير المُحددة النوع، ولكن يجب الوصول إليها باستخدام الكلمة المفتاحية "unsafe" التي قد تكون محظورة على مستوى المُصرّف. كما تدعم التحقق من صحة التحويلات أثناء التشغيل. يمكن التحقق من صحة التحويلات باستخدام الكلمة المفتاحية "as" التي تُعيد مرجعًا فارغًا (null) في حال كان التحويل غير صالح، أو باستخدام تحويل على نمط لغة C يُطلق استثناءً في حال كان التحويل غير صالح. انظر عوامل التحويل في C# .

الاعتماد المفرط على نوع الكائن (الذي تُشتق منه جميع الأنواع الأخرى) يُعرّض نظام أنواع C# لخطر الإخلال بالغرض منه. من الأفضل عادةً التخلي عن مراجع الكائنات لصالح الأنواع العامة ، على غرار القوالب في C++ والأنواع العامة في Java .

جافا

صُممت لغة جافا لضمان سلامة الأنواع. كل شيء في جافا يحدث داخل كائن ، وكل كائن هو نسخة من فئة .

لتطبيق مبدأ أمان الأنواع ، يجب تخصيص مساحة لكل كائن قبل استخدامه . تسمح لغة جافا باستخدام الأنواع الأولية ، ولكن فقط داخل الكائنات المخصصة بشكل صحيح.

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

في هذه الحالة، إذا لم يكن للقسمة تمثيل نهائي، كما هو الحال عند حساب 1/3 = 0.33333...، فقد تُثير دالة divide() استثناءً إذا لم يتم تحديد نمط تقريب للعملية. وبالتالي، تضمن المكتبة، وليس اللغة، أن يلتزم الكائن بالعقد الضمني في تعريف الفئة.

لغة الآلة القياسية

تتميز لغة ML القياسية بدلالات محددة بدقة، وهي معروفة بأمانها من حيث أنواع البيانات. مع ذلك، توفر بعض التطبيقات، بما في ذلك Standard ML of New Jersey (SML/NJ) ومتغيرها النحوي Mythryl و MLton ، مكتبات تتضمن عمليات غير آمنة. غالبًا ما تُستخدم هذه المكتبات بالتزامن مع واجهات الدوال الخارجية لتلك التطبيقات للتفاعل مع التعليمات البرمجية غير المكتوبة بلغة ML (مثل مكتبات C) التي قد تتطلب بيانات مُنسقة بطرق محددة. مثال آخر هو المستوى الأعلى التفاعلي لـ SML/NJ نفسه، والذي يجب أن يستخدم عمليات غير آمنة لتنفيذ تعليمات ML البرمجية التي يُدخلها المستخدم.

مودولا-2

Modula-2 هي لغة برمجة ذات كتابة قوية، وتعتمد فلسفة تصميمها على ضرورة تمييز أي وظائف غير آمنة بشكل صريح. ويتحقق ذلك بنقل هذه الوظائف إلى مكتبة وهمية مدمجة تُسمى SYSTEM، حيث يجب استيرادها قبل استخدامها. وبذلك، يصبح استخدامها مرئيًا عند استيراد هذه الوظائف. لسوء الحظ، لم يُطبّق هذا في التقرير الأصلي للغة ولا في تنفيذها. [ 17 ] بقيت بعض الوظائف غير الآمنة، مثل صيغة تحويل النوع وسجلات المتغيرات (الموروثة من باسكال)، والتي يمكن استخدامها دون استيراد مسبق. [ 18 ] تكمن صعوبة نقل هذه الوظائف إلى الوحدة الوهمية SYSTEM في عدم وجود مُعرّف للوظيفة التي يمكن استيرادها، إذ لا يمكن استيراد سوى المُعرّفات، وليس الصيغة.

استيراد النظام ؛ (* يسمح باستخدام بعض المرافق غير الآمنة: *) متغير كلمة : النظام . كلمة ؛ عنوان : النظام . عنوان ؛ عنوان := النظام . عنوان ( كلمة (* ولكن يمكن استخدام صيغة تحويل النوع بدون هذا الاستيراد *) VAR i : INTEGER ; n : CARDINAL ; n := CARDINAL ( i ); (* أو *) i := INTEGER ( n );

صحّح معيار ISO Modula-2 هذا الخلل في خاصية تحويل النوع، وذلك بتغيير صيغة تحويل النوع إلى دالة تُسمى CAST، والتي يجب استيرادها من الوحدة النمطية SYSTEM. مع ذلك، ظلت بعض الخصائص غير الآمنة الأخرى، مثل سجلات المتغيرات، متاحة دون الحاجة إلى استيرادها من الوحدة النمطية SYSTEM. [ 19 ]

استيراد النظام ؛ متغير i : عدد صحيح ؛ n : عدد أصلي ؛ i := SYSTEM.CAST ( عدد صحيح ، n (* تحويل النوع في ISO Modula-2 * )

طبّقت مراجعة حديثة للغة فلسفة التصميم الأصلية بدقة. أولًا، أُعيد تسمية الوحدة النمطية SYSTEM إلى UNSAFE لتوضيح طبيعة المرافق غير الآمنة المستوردة منها. ثم أُزيلت جميع المرافق غير الآمنة المتبقية كليًا (مثل سجلات المتغيرات) أو نُقلت إلى الوحدة النمطية UNSAFE. بالنسبة للمرافق التي لا يوجد لها مُعرّف قابل للاستيراد، أُضيفت مُعرّفات تمكين. ولتمكين أي مرفق، يجب استيراد مُعرّف التمكين الخاص به من الوحدة النمطية UNSAFE. لم تعد هناك أي مرافق غير آمنة في اللغة لا تتطلب الاستيراد من UNSAFE. [ 18 ]

استيراد UNSAFE ؛ متغير i : عدد صحيح ؛ متغير n : عدد أصلي ؛ i : = UNSAFE.CAST ( عدد صحيح ، n (* تحويل النوع في Modula-2 مراجعة 2010 *)FROM UNSAFE IMPORT FFI ; (* مُعرّف التمكين لمرفق واجهة الوظائف الخارجية *) <*FFI="C"*> (* توجيه برمجي لواجهة الوظائف الخارجية إلى C *)

باسكال

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

نوع TwoTypes = سجل I : عدد صحيح ; Q : عدد حقيقي ; نهاية ;DualTypes = record I : Integer ; Q : Real ; end ;var T1 , T2 : TwoTypes ; D1 , D2 : DualTypes ;

في ظل قواعد الكتابة الصارمة، لا يتوافق متغير مُعرَّف كـ TwoTypes مع DualTypes (لأنهما ليسا متطابقين، حتى وإن كانت مكونات النوع المُعرَّف من قِبل المستخدم متطابقة)، وبالتالي فإن إسناد قيمة لـ TwoTypes غير مسموح به. بينما يُعد إسناد قيمة لـ TwoTypes مسموحًا به لأن الأنواع الفرعية المُعرَّفة لها متطابقة . ومع ذلك، فإن إسناد قيمة لـ DualTypes سيكون مسموحًا به.T1 := D2;T1 := T2;T1.Q := D1.Q;

لغة الشفرة الشائعة

بشكل عام، تُعتبر لغة Common Lisp لغة آمنة من حيث النوع. يتولى مُصرّف Common Lisp مسؤولية إدراج عمليات التحقق الديناميكية للعمليات التي لا يمكن إثبات سلامة نوعها بشكل ثابت. مع ذلك، قد يُشير المبرمج إلى ضرورة تجميع برنامج بمستوى أدنى من التحقق الديناميكي من النوع. [ 20 ] لا يُمكن اعتبار البرنامج المُجمّع بهذه الطريقة آمنًا من حيث النوع.

أمثلة على لغة C++

توضح الأمثلة التالية كيف يمكن لمعاملات التحويل في لغة C++ أن تُخلّ بسلامة النوع عند استخدامها بشكل خاطئ. يُظهر المثال الأول كيف يمكن تحويل أنواع البيانات الأساسية بشكل خاطئ:

#include <iostream> using namespace std ;int main () { int ival = 5 ; // قيمة عددية صحيحة float fval = reinterpret_cast < float &> ( ival ); // إعادة تفسير نمط البت cout << fval << endl ; // إخراج العدد الصحيح كعدد عشري return 0 ; }

في هذا المثال، reinterpret_castيمنع هذا صراحةً المُصرّف من إجراء تحويل آمن من عدد صحيح إلى قيمة عشرية. [ 21 ] عند تشغيل البرنامج، سيُخرج قيمة عشرية غير صالحة. كان من الممكن تجنب هذه المشكلة بكتابة الكود التالي بدلاً من ذلك.float fval = ival;

يوضح المثال التالي كيف يمكن تحويل مراجع الكائنات إلى نوع فرعي بشكل غير صحيح:

#include <iostream> using namespace std ;class Parent { public : virtual ~ Parent () {} // مُدمِّر افتراضي لـ RTTI };class Child1 : public Parent { public : int a ; };class Child2 : public Parent { public : float b ; };int main () { Child1 c1 ; c1 . a = 5 ; Parent & p = c1 ; // التحويل التصاعدي آمن دائمًا Child2 & c2 = static_cast < Child2 &> ( p ); // تحويل تنازلي غير صالح cout << c2 . b << endl ; // سيُخرج بيانات غير صالحة return 0 ; }

تحتوي الفئتان الفرعيتان على أعضاء من أنواع مختلفة. عند تحويل مؤشر من الفئة الأصلية إلى مؤشر من الفئة الفرعية، قد لا يشير المؤشر الناتج إلى كائن صالح من النوع الصحيح. في المثال، يؤدي هذا إلى طباعة قيمة غير صالحة. كان من الممكن تجنب هذه المشكلة باستبدالها static_castبـ dynamic_cast`include` التي تُطلق استثناءً عند التحويلات غير الصالحة. [ 22 ]

انظر أيضاً

ملحوظات

  1. "ما يجب معرفته قبل مناقشة أنظمة الأنواع | أوفيد [ blogs.perl.org ] " . blogs.perl.org . تم الاسترجاع في 27-06-2023 .
  2. 1 2 ميلنر، روبن (1978)، "نظرية تعدد الأشكال في البرمجة"، مجلة علوم الحاسوب والنظم ، 17 (3): 348-375 ، doi : 10.1016/0022-0000(78)90014-4 ، hdl : 20.500.11820/d16745d7-f113-44f0-a7a3-687c2b709f66
  3. 1 2 ساراسوات ، فيجاي (15/08/1997). ""جافا ليست آمنة للنوع"" . تم الاسترجاع 2008-10-08 .
  4. رايت، أ.ك.؛ فيليسين، م. (15 نوفمبر 1994). "مقاربة نحوية لسلامة النوع" . المعلومات والحوسبة . 115 (1): 38-94 . doi : 10.1006/inco.1994.1093 . ISSN 0890-5401 . 
  5. داماس، لويس؛ ميلنر، روبن (25 يناير 1982). "مخططات الأنواع الرئيسية للبرامج الوظيفية" . وقائع الندوة التاسعة لجمعية ACM SIGPLAN-SIGACT حول مبادئ لغات البرمجة - POPL '82 . جمعية آلات الحوسبة. الصفحات 207-212 . doi : 10.1145/582153.582176 . ISBN  0897910656. S2CID 11319320 . 
  6. توفت، مادز (1988). الدلالات التشغيلية والاستدلال على النوع متعدد الأشكال (أطروحة).
  7. هنريكسن، ترولز؛ إلسمان، مارتن (17 يونيو 2021). "نحو أنواع تعتمد على الحجم لبرمجة المصفوفات" . وقائع ورشة العمل الدولية السابعة لـ ACM SIGPLAN حول المكتبات واللغات والمترجمات لبرمجة المصفوفات . رابطة آلات الحوسبة. الصفحات 1-14 . doi : 10.1145/3460944.3464310 . ISBN  9781450384667. S2CID 235474098 . 
  8. لغة النمذجة القياسية (Standard ML ). Smlnj.org. تم الاطلاع عليه بتاريخ 2013-11-02.
  9. "System.IO.Unsafe" . دليل مكتبات GHC: base-3.0.1.0 . مؤرشف من الأصل بتاريخ 2008-07-05 . تم الاطلاع عليه بتاريخ 2008-07-17 .
  10. ليسكوف، ب؛ زيلز، س (1974). "البرمجة باستخدام أنواع البيانات المجردة". إشعارات ACM SIGPLAN . 9 (4): 50-59 . CiteSeerX 10.1.1.136.3043 . doi : 10.1145/942572.807045 . 
  11. جاكسون، ك. (1977). "المعالجة المتوازية وبناء البرمجيات المعيارية". تصميم وتنفيذ لغات البرمجة . سلسلة محاضرات في علوم الحاسوب. المجلد 54. الصفحات 436-443 . doi : 10.1007/BFb0021435 . ISBN   3-540-08360-X.
  12. "CS1130. الانتقال إلى البرمجة الكائنية. – ربيع 2012 – نسخة ذاتية التعلم" . جامعة كورنيل، قسم علوم الحاسوب. 2005. تاريخ الاسترجاع: 15 سبتمبر 2023 .
  13. بيرس، بنجامين سي. (2002). الأنواع ولغات البرمجة . كامبريدج، ماساتشوستس: مطبعة معهد ماساتشوستس للتكنولوجيا. ص 158. ISBN  0-262-16209-1.
  14. وبالتالي، فإن سلامة النوع هي أيضاً مسألة تعريف جيد للفئة: يجب أن تحافظ الطرق العامة التي تُعدّل الحالة الداخلية للكائن على سلامة الكائن.
  15. كيرنيغان ؛ دينيس م. ريتشي ( مارس 1988). لغة البرمجة سي ( الطبعة الثانية). إنجلوود كليفس، نيوجيرسي : برنتيس هول . ص 142. ISBN   978-0-13-110362-7في لغة C ، الطريقة الصحيحة هي الإعلان عن أن mallocالدالة تُرجع مؤشرًا إلى void، ثم تحويل المؤشر بشكل صريح إلى النوع المطلوب باستخدام عملية التحويل.
  16. "مركز معارف IBM" . ibm.com .
  17. ^ نيكلاوس ويرث (1985). البرمجة في Modula-2 . سبرينغر فيرلاغ.
  18. 1 2 "فصل المرافق الآمنة عن غير الآمنة" . تم الاطلاع عليه بتاريخ 24 مارس 2015 .
  19. ^ "مرجع اللغة ISO Modula-2" . تم الاسترجاع 24 مارس 2015 .
  20. "Common Lisp HyperSpec" . تم الاطلاع عليه بتاريخ 26 مايو 2013 .
  21. "reinterpret_cast conversion - cppreference.com" . En.cppreference.com . تم الاطلاع عليه بتاريخ 21-09-2022 .
  22. "تحويل dynamic_cast - cppreference.com" . En.cppreference.com . تم الاطلاع عليه بتاريخ 21-09-2022 .

مراجع