
باختصار: لأننا قلنا ذلك.
:)
حسنًا ، هذا شرح قصير جدًا لمقال ، عزيزي القارئ ، وكلماتي الاستفزازية تتطلب شرحًا.
انتهى اجتماع لجنة لغة سي - الذي كان من المقرر في الأصل عقده في فرايبورغ بألمانيا ، ولكن لم ينمو معًا لأسباب واضحة - في 7 أغسطس. سارت الأمور على ما يرام وأحرزنا تقدمًا على جميع الجبهات. نعم ، نحن بالفعل نحرز تقدمًا ، أؤكد لكم أن C لم يمت.
سأذكر أيضًا أنني أصبحت محرر مشروع C ، لذا قبل أخذ العنوان على أنه تصريح جاهل من شخص كسول جدًا "لمحاولة التحسين" ، أود أن أؤكد لك أنني أعمل بجد بالفعل حتى يتمكن C لتلبية احتياجات المطورين دون الحاجة إلى ربط 50 امتدادًا محددًا من أجل بناء مكتبات وتطبيقات أكثر أو أقل جمالًا ومفيدة.
ومع ذلك قلت ذلك (إن لغة C لن تمنعك أبدًا من ارتكاب الأخطاء) ، مما يعني أنه يجب علي التبرير. يمكننا إلقاء نظرة على الآلاف من CVEs والتذاكر المرتبطة بمجموعة من التعليمات البرمجية C ، أو يمكننا جعل MISRA تتحقق بقوة من كل ميزة C من أجل إساءة الاستخدام المحتملة ( مرحبًا ، إعلانات النموذج الأولي K&R...) أو وجود أخطاء أكثر تعقيدًا ومضحكًا تتعلق بإمكانية النقل والسلوك غير المحدد. لكن بدلاً من ذلك نقرأ المصدر الأصلي - ما قالته اللجنة نفسها.
أوه ، حان الوقت للحصول على بعض الفشار ؟!
لا عزيزي القارئ ، ضع الفشار جانبًا. كما هو الحال مع جميع إجراءات ISO ، لا يمكنني اقتباس كلمات أي شخص آخر ، ولا يُقصد من هذا المقال إحراج أي شخص. لكن سأشرح لماذا لن يتم استبعاد أي شيء قد نعتبره بسهولة سلوكًا سيئًا في مستند ISO C متوافق مع المعايير. ودعنا نبدأ بالوثيقة التي أعدها دكتور فيليب كلاوس كراوس:
N2526 ، استخدم const لبيانات المكتبة التي لن يتم تعديلها .
N2526 هو مستند بسيط للغاية.
, , , . — , ! …
أوافقك الرأي ، الأمر ليس نفس الشيء تمامًا ، لكنني متأكد من أن الفكرة ستبدو معقولة لك ، عزيزي القارئ. عندما تم طرح هذه الوثيقة للتصويت ، لم يكن هناك تصويت ضدها تقريبًا. لاحقًا ، اعترض العديد من الأشخاص بشدة لأن هذا الاقتراح كسر القانون القديم. بالطبع ، هذا أمر سيء: حتى أنني التقط أنفاسي عندما أفكر في إضافة
const؟ لا توجد ABI في لغة C يمكن أن تتأثر بالابتكار. ج (تنفيذه) حتى لا يلتفت للتصفيات فكيف نكسر شيئا ؟! دعنا نلقي نظرة على سبب اعتقاد بعض الناس أن هذا سيكون تغييرًا جذريًا.
لغة ج
أو ، كما أحب أن أسميها ، "أمان الكتابة هو للغات الفاشلة". نعم ، مطول جدًا ، لذا دعنا نتوقف عند "C". قد تتساءل لماذا أقول إن لغات مثل C ليست آمنة من النوع. بعد كل شيء ، هنا:
struct Meow {
int a;
};
struct Bark {
double b;
void* c;
};
int main (int argc, char* argv[]) {
(void)argc;
(void)argv;
struct Meow cat;
struct Bark dog = cat;
// error: initializing 'struct Bark' with an expression of incompatible type 'struct Meow'
return 0;
}
لأكون صادقًا ، يبدو هذا كنوع قوي بالنسبة لي ، يا جيم! وهكذا يصبح كل شيء أكثر حدة:
#include <stdlib.h>
struct Meow {
int a;
};
struct Bark {
double b;
void* c;
};
int main (int argc, char* argv[]) {
(void)argc;
(void)argv;
struct Meow* p_cat = (struct Meow*)malloc(sizeof(struct Meow));
struct Bark* p_dog = p_cat;
// :3
return 0;
}
نعم ، يسمح معيار C لنوعين مستقلين تمامًا من المؤشرات بالإشارة إلى بعضهما البعض. سيحذرك معظم المترجمين من هذا الأمر ، لكن المعيار يتطلب منك قبول هذا الرمز ما لم تسترخي
-Werror -Wall -Wpedantic، وما إلى ذلك ، وما إلى ذلك.
في الواقع ، يمكن للمترجم أن يقبل هذا بدون صب واضح:
volatile(من يحتاج إلى هذه الدلالات على الإطلاق؟!)const(اكتب هنا أي بيانات للقراءة فقط!)_Atomic(سلامة الخيط!)
أنا لا أقول أنه لا يجب أن تكون قادرًا على القيام بكل هذا. ولكن عندما تكتب بلغة C - حيث يكون من السهل جدًا إنشاء دالة من 500-1000 سطر بأسماء متغيرة غير مفهومة تمامًا - Infa Sotka ، فأنت تعمل بشكل أساسي مع المؤشرات ، وتفتقر عمومًا إلى الأمان من حيث اللغة الأساسية. ملاحظة: هذا ينتهك القيود ، ولكن تمت كتابة الكثير من التعليمات البرمجية القديمة بالفعل لدرجة أن كل تطبيق يتجاهل بطريقة أو بأخرى المؤهلات ، ولهذا السبب ، لن يتم منع الكود الخاص بك من التجميع ( شكرًاfanf!)! في هذه الحالة ، يمكنك بسهولة تحديد كل فشل محتمل بمساعدة المترجم ، وستتلقى تحذيرات ، ولكن لن تكون مطالبًا بالتلبيس من أجل السماح للمجمع بمعرفة ما تريد فعله حقًا. والأهم من ذلك ، أن البشر الذين سيأتون من بعدك لن يفهموا أيضًا ما تعتزم القيام به.
كل ما عليك فعله هو إزالة الميزة
-Werror -Wall -Wpedantic، وستكون جاهزًا لارتكاب جرائم تعدد مؤشرات الترابط ، ووضع القراءة فقط ، وسجلات الأجهزة.
كل شيء عادل الآن ، أليس كذلك؟ إذا أزال شخص ما كل علامات التحذير والخطأ هذه ، فلن يهتم بنوع الأخطاء أو الأشياء الغبية التي تقوم بها. هذا يعني أنه في النهاية ، هذه التحذيرات غير ذات صلة تمامًا وغير ضارة فيما يتعلق بالامتثال ISO C. ومع ذلك ...
نحن نفكر في كسر التحذيرات
نعم.
هذا هو الجحيم الخاص الذي اعتاد عليه مطورو C وبدرجة أقل مطورو C ++. التحذيرات مزعجة ، وكما هو الحال في برامج التدريب ، فهي مزعجة للغاية
-Weverythingأو /W4تتضمنها. إخفاء التحذيرات المتغيرة في مساحة الاسم العالمية (شكرًا ، أصبحت جميع العناوين ومكتبات C مشكلة) ، باستخدام الأسماء "المحجوزة" (كما يقول الأطفال ، " lol nice one xd !! ") ، و "تحتوي هذه البنية على مساحة فارغة لأنك استخدمت alignof"(... نعم ، نعم ، أعلم أن لديها حشوة ، لقد طلبت صراحة المزيد من الحشو ، لأنني استخدمت alignof، السيد. COMPILATOR) - كل هذا يستغرق الكثير من الوقت.
لكن هذه تحذيرات.
حتى لو كانت مزعجة ، فإنها تساعدك على تجنب المشاكل. حقيقة أنني أستطيع تجاهل جميع المؤهلات دون خجل وإهمال جميع أنواع القراءة والكتابة والتدفق والأمان للقراءة فقط هي مشكلة رئيسية عندما يتعلق الأمر بإيصال نواياي وتجنب الأخطاء. حتى بناء جملة K&R القديم أدى إلى أخطاء في قواعد الرموز الصناعية والحكومية لأن المستخدمين كانوا يفعلون شيئًا خاطئًا. وقد فعلوا هذا ليس لأنهم كانوا مبرمجين رديئين ، ولكن لأنهم يعملون مع قواعد التعليمات البرمجية التي غالبًا ما تكون أقدم منهم ، ويستعدون للقتال معها. ملايين السطور الطويلة. من المستحيل الاحتفاظ بقاعدة الشفرة بأكملها في رأسك: الاتفاقيات والتحليل الثابت والتحذيرات عالية المستوى والأدوات الأخرى مخصصة لذلك. لسوء الحظ،
الجميع يريد أن يكون لديه رمز دون تحذيرات.
هذا يعني أنه عندما يجعل مطور دول مجلس التعاون الخليجي التحذيرات أكثر حساسية للمواقف التي قد تكون إشكالية ، يتلقى القائمون على الصيانة (وليس المطورون الأصليون) بشكل غير متوقع سجلات جريئة من عدة جيجابايت من الكود القديم ، والتي تحتوي على الكثير من التحذيرات الجديدة وجميع أنواع الأشياء المختلفة. يقولون "هذا حماقة ، لقد نجح الرمز لسنوات فلماذا تشكو دول مجلس التعاون الخليجي الآن؟" أي ، حتى لو أضفت
constوظائف إلى التوقيع ، حتى لو كان صحيحًا أخلاقيًا وروحيًا وفعليًا ، فسيتم تجنب ذلك. يعني "كسر" الأشخاص "الآن عليهم البحث عن رمز به نوايا مشكوك فيها". هذا رمز يمكنه - تحت وطأة السلوك غير المحدد - تدمير شريحتك أو إتلاف ذاكرتك.... لكن هذه مشكلة أخرى ترافق مهنة مطور C هذه الأيام.
العمر كمقياس للجودة
كم عدد الأشخاص الذين افترضوا أن
sudoلديهم ضعف بدائي مثل "-1 أو فيض عدد صحيح يتيح الوصول إلى كل شيء"؟ كم من الناس اعتقدوا أن Heartbleed يمكن أن تكون مشكلة حقيقية؟ كم عدد مطوري الألعاب الذين يشحنون مكتبات stb "الصغيرة" دون استخدام أي جهاز فيسر وعدم إدراك أن هذه المكتبات تحتوي على نقاط ضعف في الإدخال أكثر أهمية مما قد تتخيله؟ أنا لا أنتقد كل هذه التطورات أو مؤلفيها: فهم يزودوننا بمساعدة حيوية ، اعتمد عليها العالم لعقود ، غالبًا بدعم ضئيل أو معدوم حتى ظهور مشكلة كبيرة. لكن الأشخاص الذين يعبدون هذه التطورات ويضعونها بمفردهم ، ثم ينثرون قولًا مسمومًا من أنفسهم يوضح خطأ الناجي:
, ?
مع الحفاظ على مبادئ التوافق مع الإصدارات السابقة و "الاسترخاء" كأعلى مُثُل لـ C ، يبدأ الأشخاص الذين بقوا على قيد الحياة لفترة كافية في هذه الصناعة في مساواة العمر بالجودة ، مثل الأكواد البرمجية براميل النبيذ. كلما تم استخدام الكود الأقدم والأطول ، كان النبيذ أفضل وأكثر دقة.
لسوء الحظ ، كل شيء ليس رومانسيًا ولطيفًا: مليء بالأخطاء ، مع وفرة من الثغرات الأمنية ، كل هذا الدين التقني يزداد خطورة كل يوم. بمرور الوقت ، تتحول جميع الأنظمة إلى أكوام متعفنة ذات عمر نصف وغير مهذب وغير مدعومة جزئيًا. لقد تم تزيينها وإعطائها روح النبلاء ، لكنها في الواقع مومياوات تنتظر فقط أن يتم طعنها بشكل محرج ، وبعد ذلك ستنفجر الدمامل المتقيحة التي تسبق الطوفان وتغمر تطبيقك بتسممها الغذائي الرائع.
حسنًا ... مقرف. لكن ماذا عن المعيار ج؟
المشكلة التي لاحظتها خلال فترة عملي (القصيرة للغاية) كمشارك في الاجتماع هي أننا وضعنا التوافق مع الإصدارات السابقة في المقدمة. بالنسبة لأولئك الذين يهاجرون إلى C اليوم ، فإننا نحتفظ بالتطبيقات القديمة وحالات استخدامها ونحرم أنفسنا من فرصة تحسين أمان أو أمان أو فن كود C. ، يمكنه إيقاف تشغيلها. هذه التحذيرات ، وليست الأخطاء ، ليست عبثًا: لا تتطلب آلة C مجردةلإجراء التشخيص ، تسمح ISO C بقبول هذا الرمز في أوضاع التجميع الصارمة. وهذا من شأنه أن يساعد العالم بأسره على الابتعاد عن واجهات برمجة التطبيقات التي تنص علانية على أن "تغيير المحتوى الذي نقدمه لك هو سلوك غير محدد"
ومع ذلك ، فقد غيرنا رأينا بشأن هذه الوثيقة بعد أن تم تقديمها كسبب "لا يمكننا تقديم تحذيرات جديدة".
كانت الحجة ضد الاقتراح: "هناك الكثير من التعليمات البرمجية المكتوبة التي ستنكسر إذا قمنا بتغيير هذه التوقيعات." هذا ، مرة أخرى ، يحد من التغييرات في التحذيرات من حيث السلوك المتقطع (تذكر ، التحويلات الضمنية التي تزيل المؤهلات - حتى
_Atomic- صالحة تمامًا وفقًا لمعيار ISO C ، حتى لو خالفت القيود). إذا كان الأمر كذلك ، فإن كل مؤلف مترجم سيقدم شيئًا مثل Ages in Rust ، For Warnings فقط ، لمنح الأشخاص معيارًا "ثابتًا" للاختبار. هذا الاقتراح ليس جديدًا: لقد قرأت مستندات مماثلة من مهندسي Coverity حول إنشاء تنبيهات جديدة وكيفية تفاعل المستخدمين معها. من الصعب إدارة "ثقة" المطورين بشأن التحذيرات الجديدة وأشياء أخرى. يستغرق إقناع الناس بفائدتهم وقتًا طويلاً. حتى جون كارماك كان عليه أن يعمل بجد للحصول على المجموعة الصحيحة من التحذيرات والأخطاء من أدوات التحليل الثابتة الخاصة به لتناسب تطوره ، قبل أن يستنتج أنه "من غير المسؤول عدم استخدام هذا" .
ومع ذلك ، فإننا ، اللجنة ، لم نوافق على إضافة
constوظائف إرجاع القيمة إلى الوظائف الأربع لأن ذلك من شأنه أن يضيف تحذيرات إلى رمز يحتمل أن يكون خطيراً. لقد اعترضنا على إهمال بناء جملة K&R القديم ، على الرغم من وجود أدلة قوية على كل من الإغفالات البريئة ونقاط الضعف الخطيرة الناشئة عن تمرير الأنواع الخاطئة. لقد أضفنا تقريبًا سلوكًا غير محدد إلى المعالج المسبق ، فقط لإزالته ، ولكن لجعل تطبيق C "يتصرف كما ينبغي". نظرًا للتوافق مع الإصدارات السابقة ، فإننا نسير دائمًا على الحافة لتجنب ارتكاب أخطاء واضحة. وهذا ، عزيزي القارئ ، يخيفني أكثر بشأن مستقبل S.
المعيار C لا يحميك
لا تخطئ: لا يهم ما يخبرك به المبرمجون أو ما يهمسوه لك. اللجنة التوجيهية للغة C واضحة جدًا. لن نضيف تحذيرات جديدة إلى شفرتك القديمة ، حتى لو كان هذا الرمز خطيرًا. لن نمنعك من ارتكاب الأخطاء ، لأنها يمكن أن تقوض فكرة كيفية عمل الكود القديم ، وهذا خطأ. لن نساعد المبتدئين في كتابة كود C أفضل. ولن نطلب رمزك القديم ليتوافق مع أي معيار. ستكون كل ميزة جديدة اختيارية لأننا لا نستطيع تخيل إجبار مؤلفي المترجمين على الالتزام بمعايير أعلى أو توقع المزيد من مطوري مكتباتنا القياسية.
سنترك المترجم يكذب عليك. سنكذب على شفرتك. وعندما يسير كل شيء بشكل خاطئ - سيكون هناك خطأ ، "أوه ، حدث نوع من القمامة" ، سيكون هناك تسرب للبيانات - سنهز رؤوسنا بجدية. سوف نشارككم بأفكارنا ونصلي من أجلكم ونقول ، "حسنًا ، يا له من عار". في الواقع ، العار ...
ربما في يوم من الأيام سنصلحه ، عزيزي القارئ.