لغة البرمجة Cyclone
صُممت لغة البرمجة Cyclone لتكون لهجة آمنة من لغة C. [ 2 ] وهي تتجنب ثغرات تجاوز سعة المخزن المؤقت وغيرها من الثغرات الأمنية المحتملة في برامج C، دون أن تفقد قوة لغة C وسهولة استخدامها كأداة لبرمجة الأنظمة . لم يعد مطوروها الأصليون يدعمونها، كما أن أدواتها المرجعية لا تدعم منصات 64 بت . وقد أشار المطورون الأصليون إلى لغة Rust لاحتوائها على العديد من الأفكار نفسها التي اعتمدتها Cyclone. [ 3 ]
بدأ تطوير برنامج Cyclone كمشروع مشترك بين تريفور جيم من مختبرات أبحاث AT&T ومجموعة جريج موريسيت في جامعة كورنيل في عام 2001. تم إصدار الإصدار 1.0 في 8 مايو 2006. [ 4 ]
خصائص اللغة
يسعى برنامج Cyclone إلى تجنب بعض المشاكل الشائعة في لغة C ، مع الحفاظ على مظهرها وأدائها. ولتحقيق هذه الغاية، يفرض Cyclone القيود التالية على البرامج:
NULLتُضاف عمليات التحقق لمنع أخطاء تجزئة الذاكرة .- العمليات الحسابية للمؤشرات محدودة
- يجب تهيئة المؤشرات قبل استخدامها (يتم فرض ذلك من خلال تحليل التعيين المحدد ).
- يتم منع المؤشرات المعلقة من خلال تحليل المنطقة ووضع قيود على
free() - لا يُسمح إلا بالجبائر والوصلات "الآمنة".
gotoيُمنع استخدام النطاقات الداخلية.switchلا يُسمح باستخدام التصنيفات في نطاقات مختلفة.- يجب تنفيذ الدوال التي تُرجع مؤشرًا
return setjmpوغيرlongjmpمدعومة
للحفاظ على مجموعة الأدوات التي اعتاد عليها مبرمجو لغة C، يوفر Cyclone الإضافات التالية:
NULLلا تتطلب المؤشرات التي لا تستخدم أبدًاNULLعمليات تحقق- تدعم المؤشرات "السمينة" العمليات الحسابية على المؤشرات مع التحقق من حدود وقت التشغيل
- تدعم المناطق القابلة للتوسيع شكلاً من أشكال إدارة الذاكرة اليدوية الآمنة
- جمع البيانات المهملة للقيم المخصصة في الذاكرة الديناميكية
- المؤشرات الذكية ، مثل المؤشرات الفريدة
- إدارة الذاكرة القائمة على المناطق
- تدعم الاتحادات الموسومة الوسائط المتغيرة النوع
- تساعد عمليات الحقن في أتمتة استخدام الاتحادات الموسومة للمبرمجين
- يحل تعدد الأشكال محل بعض استخدامات
void* - يتم تنفيذ الوسائط المتغيرة كمؤشرات سميكة
- تُستبدل بعض استخدامات "
setjmpو" باستثناءات .longjmp - مساحات الأسماء
- استنتاج النوع
- مطابقة الأنماط
- القوالب ، الأنواع ذات المعاملات
تبدو لغة Cyclone، بشكل عام، شبيهة بلغة C، ولكن يجب اعتبارها لغة شبيهة بلغة C.
أنواع المؤشرات
تُنفذ Cyclone ثلاثة أنواع من المؤشرات :
*(النوع العادي)@(NULLالمؤشر الذي لا يستخدم أبدًا)، و?(النوع الوحيد المسموح فيه بحسابات المؤشرات ، المؤشرات "السمينة" ).
الهدف من تقديم أنواع المؤشرات الجديدة هذه هو تجنب المشاكل الشائعة عند استخدام المؤشرات. لنأخذ على سبيل المثال دالة، تُسمى foo، تأخذ مؤشرًا إلى عدد صحيح (int):
int foo ( int * p );على الرغم من أن كاتب الدالة fooكان بإمكانه إضافة NULLعمليات تحقق، فلنفترض أنه لم يفعل ذلك لأسباب تتعلق بالأداء. foo(NULL);سيؤدي استدعاء الدالة إلى سلوك غير محدد (عادةً، وإن لم يكن بالضرورة، إرسال SIGSEGVإشارة إلى التطبيق). لتجنب هذه المشاكل، يُقدّم Cyclone @نوع المؤشر، الذي لا يمكن أن يكون فارغًا أبدًا . وبالتالي، ستكون NULLالنسخة "الآمنة" من الدالة كالتالي :foo
int foo ( int @ p );يُخبر هذا مُصرّف Cyclone أن الوسيط المُمرّر إلى الدالة fooيجب ألا يكون أبدًا صفرًا NULL، مما يُجنّب السلوك غير المُعرّف المذكور سابقًا. يُغني هذا التغيير البسيط من *صفر إلى صفر @المبرمج عن كتابة NULLعمليات التحقق، ويُجنّب نظام التشغيل عناء معالجة NULLحالات الوصول غير المُعرّف إلى المؤشرات. مع ذلك، قد يُمثّل هذا الحد الإضافي عقبة كبيرة أمام مُعظم مُبرمجي لغة C، الذين اعتادوا على التعامل مع مؤشراتهم مُباشرةً باستخدام العمليات الحسابية. على الرغم من أن هذا مرغوب فيه، إلا أنه قد يُؤدي إلى تجاوزات في سعة المخزن المؤقت وأخطاء أخرى من نوع "الخطأ بمقدار واحد". لتجنّب ذلك، ?يتم تحديد نوع المؤشر بحدّ معروف، وهو حجم المصفوفة. على الرغم من أن هذا يُضيف عبئًا إضافيًا بسبب المعلومات الإضافية المُخزّنة حول المؤشر، إلا أنه يُحسّن السلامة والأمان. لنأخذ على سبيل المثال strlenدالة بسيطة (وساذجة) مكتوبة بلغة C:
دالة طول السلسلة ( متغير ثابت من نوع char * s ) { int i = 0 ; if ( ! s ) { return 0 ; } while ( s [ i ] != '\0' ) { i ++ ; } return i ; }تفترض هذه الدالة أن السلسلة المُمرَّرة تنتهي بفاصلة '\0'. إذا مُرِّرت إلى هذا الكود سلسلة غير منتهية ، فسيتجاوز التكرار نهاية السلسلة، ليصل إلى ذاكرة غير مرتبطة بها. تسعى دوال C غير المتوافقة مع معيار ANSI، مثل تلك المذكورة، إلى معالجة هذه المشاكل.charbuf[6]={'h','e','l','l','o','!'};strlenstrnlen
نسخة الإعصار strlenمشابهة للنسخة C:
دالة `strlen` تأخذ وسيطًا من نوع ` char` كمدخل، وتحسب طول السلسلة `s`. إذا لم يكن طول السلسلة ` s` كافيًا ، تُرجع الدالة ` 0` . ثم تُكرر العملية على جميع عناصر السلسلة `s` ، مع التحقق من أن طول السلسلة `s` يساوي ` \ 0` . إذا كان طول السلسلة ` s` يساوي ` \0` ، تُرجع الدالة ` i` . في النهاية، تُرجع الدالة ` n` .هنا، strlenيُحدد المؤشر نفسه بطول المصفوفة المُمررة إليه. يمكن تحويل كل نوع من أنواع المؤشرات بأمان إلى الأنواع الأخرى، ويقوم ?المُصرّف بتحويل المصفوفات والسلاسل النصية تلقائيًا. (يؤدي التحويل من نوع إلى آخر إلى إجراء فحص للحدود ، بينما يؤدي التحويل من نوع ?إلى آخر إلى إجراء فحصين : فحص للحدود وفحص للمؤشر. أما التحويل من نوع إلى آخر فلا يُجري أي فحوصات على الإطلاق؛ ويكون حجم المؤشر الناتج 1).*?@NULL*??
المؤشرات المعلقة وتحليل المنطقة
انظر إلى الكود التالي، المكتوب بلغة C:
char * itoa ( int i ) { char buf [ 20 ]; sprintf ( buf , "%d" , i ); return buf ; }تُخصّص الدالة itoaمصفوفة من الأحرف bufعلى المكدس وتُعيد مؤشرًا إلى بدايتها buf. مع ذلك، يتم تحرير الذاكرة المُستخدمة على المكدس bufعند انتهاء الدالة، لذا لا يُمكن استخدام القيمة المُعادة بأمان خارج الدالة. على الرغم من أن مجموعة مُترجمات GNU وغيرها من المُترجمات تُحذّر من هذا النوع من التعليمات البرمجية، إلا أن ما يلي يُترجم عادةً دون تحذيرات:
char * itoa ( int i ) { char buf [ 20 ]; sprintf ( buf , "%d" , i ); char * z = buf ; return z ; }يمكن لمجموعة مُترجمات GNU إصدار تحذيرات لمثل هذا الكود كأثر جانبي للخيار -O2أو -O3، ولكن لا توجد ضمانات لاكتشاف جميع هذه الأخطاء. يُجري Cyclone تحليلًا إقليميًا لكل جزء من الكود، مانعًا المؤشرات المُعلقة، مثل المؤشر المُعاد من هذه النسخة من itoa. تُعتبر جميع المتغيرات المحلية في نطاق مُحدد جزءًا من نفس المنطقة، منفصلة عن الكومة أو أي منطقة محلية أخرى. وبالتالي، عند تحليل itoa، سيرى مُترجم Cyclone أن zهو مؤشر إلى المكدس المحلي، وسيُبلغ عن خطأ.
مؤشرات الدهون
يُستخدم المؤشر السميك لإجراء العمليات الحسابية على المؤشرات. يجب تعريف المؤشرات السميكة باستخدام ` . على@fat سبيل المثال، argvغالبًا ما يُعرَّف المؤشر السميك كنوع char**(مؤشر إلى مؤشر إلى حرف)، أو يُنظر إليه char*[]كمؤشر إلى مصفوفة من الأحرف. في Cyclone، يُعبَّر عنه char*@fat*@fatكمؤشر سميك إلى مؤشر سميك إلى أحرف.
يسمح برنامج Cyclone بدلاً من ذلك ?بتمثيل *@fat. وبالتالي، فإن الإعلانين متكافئان:
int main ( int argc , char ?? argv ); // مكافئ للتصريح الأكثر تفصيلاً int main ( int argc , char * @ fat * @ fat argv );أنواع مُعَلمة
على غرار القوالب في لغة C++ ، فإن Cyclone لديه شكل من أشكال البرمجة العامة .
typedef struct LinkedList < ` a > { ` a head ; struct LinkedList < ` a >* next ; } LinkedList < ` a > ;// ... LinkedList <int> * ll = new LinkedList { 1 , new LinkedList { 2 , null } } ;يمكن استخدام نوع "مجرد" يغلف نوع التنفيذ ولكنه يضمن عدم تسرب التعريف إلى العميل.
abstract struct Queue < ` a > { LinkedList < ` a > front ; LinkedList < ` a > rear ; };extern struct Queue < ` a > ;مساحات الأسماء
توجد مساحات الأسماء في Cyclone، على غرار لغة C++. تُستخدم مساحات الأسماء لتجنب تضارب الأسماء في الكود، وتتبع ::نفس طريقة الترميز في C++. يمكن تداخل مساحات الأسماء.
namespace foo { int x ; int f () { return x ; } }namespace bar { using foo { int g () { return f (); } }int h () { return foo :: f (); } }مطابقة الأنماط
يمكن إنجاز مطابقة الأنماط في برنامج Cyclone على النحو التالي:
دالة g ( عدد صحيح a ، عدد صحيح b ) { switch ( $ ( a , b - 1 )) { case $ ( 0 , y ) && y > 1 : return 1 ; case $ ( 3 , y ) && f ( x + y ) == 7 : return 2 ; case $ ( 4 , 72 ): return 3 ; default : return 4 ; } }letيُستخدم الإعلان لمطابقة نمط وتعبير .
typedef struct Pair { int x ; int y ; } Pair ;void f ( Pair p ) { let Pair ( first , second ) = p ; // مكافئ لـ: // int first = px; // int second = py; // ... }استنتاج النوع
في Cyclone، بدلاً من استخدام autoمثل C و C++ أو varفي Java و C# ، يستخدم Cyclone بدلاً من ذلك _(شرطة سفلية) للدلالة على متغير مستنتج من النوع.
_ x = ( SomeType * ) malloc ( sizeof ( SomeType )); // بدلاً من: SomeType x = ( SomeType * ) malloc ( sizeof ( SomeType ));_ myNumber = 100 ; // يُستنتج أنه عدد صحيحالاستثناءات
تتضمن لغة Cyclone استثناءات . سيؤدي حدوث استثناء غير معالج إلى إيقاف البرنامج. ومثل لغة Java، تتضمن Cyclone استثناء مؤشر فارغ ، يُسمى Null_Exception.
typedef FILE File ;File * f = fopen ( "/etc/passwd" , "r" ); try { int code = getc (( File * @ notnull ) f ); } catch { case & Null_Exception : printf ( "خطأ: لا يمكن فتح /etc/passwd \n " ); return 1 ; case & Invalid_argument ( s ): printf ( "خطأ: وسيطة غير صالحة: %s \n " , s ); return 1 ; }يمكن أيضًا طرح الاستثناءات يدويًا:
throw new Null_Exception ( "هذا استثناء فارغ" );انظر أيضاً
مراجع
- ↑ "Cyclone لمبرمجي لغة C" . cyclone.thelanguage.org . تم الاطلاع عليه بتاريخ 12 أكتوبر 2025 .
- ↑ جيم، تريفور؛ موريسيت، ج. جريج؛ جروسمان، دان؛ هيكس، مايكل و.؛ تشيني، جيمس؛ وانغ، يانلينج (10 يونيو 2002). "سايكلون: لهجة آمنة من لغة سي" . وقائع المسار العام للمؤتمر التقني السنوي لجمعية يوسينكس . ATEC '02. الولايات المتحدة الأمريكية: جمعية يوسينكس: 275-288 . ISBN 978-1-880446-00-3.
- ↑ "إعصار" . cyclone.thelanguage.org . مؤرشف من الأصل في 21 مايو 2006. تم الاطلاع عليه في 11 ديسمبر 2023 .
- ↑ "إعصار" . جامعة كورنيل . مؤرشف من الأصل في 15 أكتوبر 2022. تم الاطلاع عليه في 30 أكتوبر 2022 .
روابط خارجية
- الصفحة الرئيسية لـ Cyclone
- موقع ويب قديم
- مستودعات شفرة المصدر لبرنامج Cyclone
- الأسئلة الشائعة حول الإعصار
- برنامج Cyclone لمبرمجي لغة C
- دليل مستخدم جهاز Cyclone
- Cyclone: a Type-safe Dialect of C by Dan Grossman, Michael Hicks, Trevor Jim, and Greg Morrisett – published January 2005
العروض التقديمية:
- إعصار: لهجة آمنة من نوع C
- سايكلون: لغة برمجة آمنة للذاكرة من مستوى لغة سي
- عائلة لغات البرمجة C
- لغات البرمجة التي تم إنشاؤها في عام 2002
