البرمجة

فترة حياة الكائنات الرمزية في C: تأثير الكتل البرمجية

السؤال النظري الذي طرحته يتعلق بعمر الكائن الرمزي (compound literal) في لغة البرمجة C وكيف يتأثر ذلك بالكتل البرمجية المحيطة به، خاصةً في حالة البنية التكرارية واستخدامها داخل بنيات if.

لنبدأ بفحص الشيفرة البرمجية المقدمة. يتم تعريف هيكلين foo و bar، وثم تعريف دالة init_bar التي تقوم بتخصيص مساحة في الذاكرة لهيكل bar وتهيئته بمؤشر إلى هيكل foo الممرر إليها. في المتغير x، يتم استدعاء init_bar بواسطة تكوين مباشر (compound literal)، ومن ثم يتم زيادة قيمة a في foo المرتبطة بمتغير b، وأخيراً يتم حرر الذاكرة المخصصة.

الفحص الأول يتعلق بالمبرمج “غير المهذب” الذي لا يقوم بفحص قيمة العائدة من init_bar. الشيفرة تعمل، ولكن هنا يطرح السائل تساؤلًا عن السلوك المحتمل، خاصة فيما يتعلق بمدى صحة تعديل struct foo عبر المؤشر الموجود في struct bar.

ثم يتم تقديم النسخة الأكثر حذرًا، حيث يتم التحقق من قيمة العائدة من init_bar. وهنا يثير السائل مشكلة نظرية تتعلق بفترة حياة الكائن الرمزي. يستند إلى القسم 6.5.2.5 من معيار C11، الذي يشير إلى أنه “إذا حدث الكائن الرمزي خارج جسم الدالة، فإن لديه تخزين ثابت، وإلا، فإن لديه تخزين تلقائي يتعلق بالكتلة المحيطة”.

الشك يأتي من فهم كلمة “كتلة” في هذا السياق. هل تعني الكتلة البرمجية بأكملها، أم تقتصر على البيانات داخل هيكل if؟ وهنا تقع القضية في المراجعة.

التساؤل الأساسي هو ما إذا كانت فترة حياة الكائن الرمزي محصورة في كتلة if. وفقًا للقسم 6.8.4 من المعيار الذي يتحدث عن “بيانات الاختيار” (selection statements) ويشير إلى أن “البيانات الاختيارية هي كتلة تنطوي على مدى فرعي صارم لنطاق كتلة الاختيار الخاصة بها”. هذا يعني أن الكائن الرمزي يعيش فقط طوال حياة الكتلة if.

هنا، يكون الاستنتاج هو أن الشيفرة في دالة y قد تؤدي إلى سلوك غير محدد (undefined behavior)، حيث يمكن أن يكون الإشارة إلى الكائن الرمزي غير صالح بعد انتهاء الكتلة if.

في الختام، يظهر هذا النقاش كيف يمكن أن تكون تفاصيل فنية في لغة البرمجة C معقدة وتحتاج إلى اهتمام دقيق بالتفاصيل لتجنب السلوك غير المحدد والمشاكل المحتملة.

المزيد من المعلومات

في سياق النقاش الحالي، يمكن أن نستعرض بعض المفاهيم والتفاصيل الإضافية لفهم أفضل لسياق المعايير في لغة C.

لنتحدث أكثر عن الفترة الزمنية للكائنات الرمزية. يعد قسم 6.2.4 من معيار C11 هو القسم المعني بالفترة الزمنية للمتغيرات ويعرِّف أنواع الفترة الزمنية الرئيسية ثلاثة: الثابتة (static)، والتلقائية (automatic)، والديناميكية (allocated).

  • تخزين ثابت (Static Storage Duration): تطبق على المتغيرات التي تُعلن خارج الدوال وتُبدأ فترتها الزمنية عند بداية تنفيذ البرنامج وتستمر حتى نهايته. تطبيق تخزين ثابت يتضمن العديد من القواعد المعينة في معيار C.

  • تخزين تلقائي (Automatic Storage Duration): تطبق على المتغيرات التي تُعلن داخل الدوال دون استخدام الكلمة الرئيسية static. تبدأ فترتها الزمنية عند دخول الدالة وتنتهي عند انتهاء الدالة.

  • تخزين دينامي (Allocated Storage Duration): تطبق على المتغيرات التي تُخصص في الذاكرة باستخدام وظائف مثل malloc، وتنتهي عند استدعاء free.

بالنسبة للكائنات الرمزية في سياق النقاش، القسم 6.5.2.5 الذي تم الإشارة إليه يعرف أنه إذا حدثت الكائنات الرمزية داخل جسم دالة، فإنها تكون لديها تخزين تلقائي يتعلق بالكتلة المحيطة بها.

مع ذلك، يجب أن نلفت الانتباه أيضًا إلى القسم 6.7.9 الخاص بـ “بيانات الكتلة” (block scope) والذي ينص على أن “المتغيرات التي تتم إعادة تعريفها في كتلة لديها نطاق الكتلة”. هذا يعني أن فترة حياة المتغير يمكن أن تكون محصورة في الكتلة التي يتم فيها تعريفها.

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

زر الذهاب إلى الأعلى