الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

سؤال عن حجم البنية وكيفية التعامل معها

مغلقمُجاب
بدأه abdelhak13 في 3 أبريل 2014 · 12 رد · 827 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم كنت اشتغل على برنامج لادارة طلبة كتمرين ها هو الكود لبرنامج كتبته من اجل توضيح المشكل الذي يحدث 


الصورة توضح ماذا يحدث عندما يتم الادخال 


 


 


كما تلاحظون بالنسبة للمتغير الاول في البينة حتا لو تجاوزنا المساحة المخصصة له واعدنا الادخال يتم القراءة بالنجاح 


ولكن المتغير الثاني لو تجاوزنا المساحة المخصصة له وقرأنا يظهر الخطأ في الصورة 


هذا المشكل لا يحدث عندما يتم الاعلان عنه كعام 


 


صراحة المشكل لم افهم ماذا يحدث بصفة نهائية في الذاكرة 


ممكن الشرح لي لماذا هذا المشكل يحدث وما الحل غير ان يتم الاعلان عنه خارج الدالة لاني اريد حل المشكل داخل الدالة 


 


ولدي استفسار آخر وهو ان تم الاعلان عن متغير حرفي فيه سلسلة من الحروف مثلا طوله 5 ولم يتم اعطاءه اي شئ فما الذي يوضع فيه من قبل البرنامج ؟؟؟


تم تعديل هذه المشاركة بواسطة abdelhak13 في 4 أبريل 2014 في 03:07

#2 أفضل إجابة

لما تضع البنية داخل الدالة فهي ستخزن داخل مكدس الدالة، لما أدخلت نص طويل أطول من حجم المتغير فحصل عندك طفح في المكدس stack overflow وكتبت فوق عنوان العودة للدالة main، الآن لما الدالة main تعمل return فستعود لمنطقة عشوائية في البرنامج وسينهار البرنامج. الخطأ لايظهر مباشرة في المتغير العام لأنه مخزن في قسم البيانات وليس المكدس، لكن في كلا الحالتين هناك طفح والبرنامج يخرب نفسه.

 

هذا المثال لمتغير عام يوضح لك أنه لايزال هناك خطأ:

#include <stdio.h>
#include <string.h>

char a[3];
char b[3];

int main()
{
  gets(a);
  printf("a = %s, b = %s\n", a, b);

  return 0;
}
> example.exeAAABBBBa = AAABBBB, b = BBBB>

قرأت فقط a لكن البيانات أكبر من أن يتحملها ثم طفح والزيادة ظهرت في b، لأنهما متجاوران في الذاكرة.

 

اقتباس

 

ولدي استفسار آخر وهو ان تم الاعلان عن متغير حرفي فيه سلسلة من الحروف مثلا طوله 5 ولم يتم اعطاءه اي شئ فما الذي يوضع فيه من قبل البرنامج ؟؟؟

 

إذا كان المتغير محلي، فقيم عشوائية، غالباً بيانات من اطار مكدس stack frame لدالة سبق أن استدعيت:

#include <stdio.h>

void func1()
{
  int a = 3;
  printf("%d\n", a);
}

void func2()
{
  int a; // غير مهيأ
  printf("%d\n", a);
}


int main()
{
  func1();
  func2(); // قد يطبع ثلاثة!
  return 0;
}

لاتعتمد عليه.

 

إذا كان متغير عام فهو دائماً سيهأ بصفر.

تم تعديل هذه المشاركة بواسطة Mr.B في 4 أبريل 2014 في 01:05

2
#3

ممكن ان تقول لي كيف نتجاوز هذا المشكل الخاص بالفيض في الذاكرة 

مثلا لدينا متغيرين الاسم الاول والثاني 

مثلا المستخدم ادخل اسم طويل وحصل فيض اي سيحدث في الاسم الثاني 

اعدناهليدخل الاسم الاول وتم الامر جيدا ولكن الفيض موجود في الاسم الثاني لنفرض انه لا يوجد لديه اسم ثاني عند الطباعة سيطبع الاسم الاول صحيح ولكن الثاني سيطبع بقايا الاسم في البداية كيف نتجاوز هذا 

 

ممكن ان تشرح ليك الفرق بين مكدس الدالة والمكدس هل هما نفسهما وهل المنطقة تابتة في الذاكرة ام هي يتم حجزها كلما تمت الحاجة لذلك وكم يكون مساحتها ؟

#4

الحل أنك لاتقرأ أكثر ممايستوعبه المتغير، gets غير آمنه عموماَ، يمكنك استخدام scanf هكذا:

#include <stdio.h>

int main()
{
  char name[11]; // عشرة حروف للاسم وواحد للصفر الذي يحدد نهاية النص

  printf("name?> ");
  scanf("%10[^\n]s", name);
  // 10    اقرأ فقط عشرة حروف على الأكثر
  // [^\n] اقرأ إلى نهاية السطر وليس فقط كلمة
  printf("%s\n", name);

  return 0;
}

حجم المكدس غير ثابت، كل thread في عملية البرنامج يخصص نظام التشغيل مكدس خاص فيه ويزيد حجمه متى مادعت الحاجة. مكدس الدالة يسمى stack frame، وهو جزء مخصص لهذه الدالة عندما تستدعى أول مرة لتخزين المتغيرات المحلية ثم ينتهي عندما تعمل return، لاتشغل بالك به الآن إذا كنت طالب ستدرس عنه عندما تأخذ مادة الأسمبلي.

تم تعديل هذه المشاركة بواسطة Mr.B في 4 أبريل 2014 في 02:01

#5

شكرا لك كثيرا يا اخي على الشرح والله 

 

قلت

 

وكتبت فوق عنوان العودة للدالة main، الآن لما الدالة main تعمل return فستعود لمنطقة عشوائية

 

لكن يا اخي بعد تجربة البرنامج يطهر ان الدالة تعيد قيمة كما مطلوب منها رفم اني قمت بعمل فيض في المتغير 

 

انا اسف كثيرا على كثيرة الاسئلة ولكن انا ادرس فقط في مركز تكوين ولا نتحصص كثيرا لهذا اعرف ان هذه الامور لن ندرسها لهذا اسأل واتمنى ان لا اكون اكثرت عليك 

#6

لم أكن أشير إلى القيمة التي تعيدها الدالة، بل العودة للمكان الذي استدعيت منه.

 

عندما تكتب بيانات خارج حدود متغير فهناك بيانات خربت ولايمكن الجزم بتأثيرها على سير البرنامج، أحياناً الخطأ لايظهر أو لايظهر مباشرة، لكن في كل الحالات هناك خطأ في البرنامج.

تم تعديل هذه المشاركة بواسطة Mr.B في 4 أبريل 2014 في 02:16

#7
Mr.B كتب:

لم أكن أشير إلى القيمة التي تعيدها الدالة، بل العودة للمكان الذي استدعيت منه.

 

عندما تكتب بيانات خارج حدود متغير فهناك بيانات خربت ولايمكن الجزم بتأثيرها على سير البرنامج، أحياناً الخطأ لايظهر أو لايظهر مباشرة، لكن في كل الحالات هناك خطأ في البرنامج.

نعم اخي الآن فهمت ما الذي تقصد بهذا 

اخي في اطار محاولتي لحل هذا المشكل بنفسي قمت بكل مرة باظهار طول متغير فيه كلمة استعملت الدالة strlen عندما اقوم بظهار المتغير وهو لا يوجد شئ فيه لا يظهر اي شئ في الكونسول ولا حتى قفزة انا متأكد من هذا 

وعند اظهار طول المتغير يظهر واحد ما هو يا اخي الموجود فيه ؟ 

ممكن ان تقول لي عندما الدالة strlen لا يوجد اي شئ في المتغير ما الذي تعيده ؟

#8

هل تستخدم strlen مع متغير لم تهيأة؟ المتغيرات غير المهيأة ستحتوي بيانات عشوائية (ليس فارغة كما قلت)، قد تكون أي شيء وقد تعطيك strlen أي رقم أو حتى قد ينهار برنامجك. المتغيرات الوحيدة التي تهيأ إفتراضياً في c بأصفار هي المتغيرات العامة والثابته static.

1
#9
Mr.B كتب:

هل تستخدم strlen مع متغير لم تهيأة؟ المتغيرات غير المهيأة ستحتوي بيانات عشوائية (ليس فارغة كما قلت)، قد تكون أي شيء وقد تعطيك strlen أي رقم أو حتى قد ينهار برنامجك. المتغيرات الوحيدة التي تهيأ إفتراضياً في c بأصفار هي المتغيرات العامة والثابته static.

 

شكرا لك اخي كثيرا على شرحك لي وصبرك معي 

 

لدي الكثير من الاسئلة ولكن نكتفي بهذا القدر لاني ارهقتك معي 

 

جزاك الله خيرا

#10

آخر سؤال له علاقة بالموضوع 

هل الاعلان هكذا 

char name[5];  char name2[5];

يعني ان البيتات التي سيتم حجزها في الذاكرة يتكون بجانب بعضها لاني قمت بفيض في الذاكرة في المتغير الاول يعني ان كانا بجانب بعضها سيفيض على المتغير الثاني وبهذا عند اظهارهماسيظهر جزء من الاول في الثانية 

ولكن لم يظهر بل رمز عشوائي كما قلت ..؟؟

#11

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

تم تعديل هذه المشاركة بواسطة Mr.B في 4 أبريل 2014 في 03:11

#12
Mr.B كتب:

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

 

نعم بالفعل يتم عكس المتغيرات وعند الاعلان عن بينة من فيها متغيرين نفس الاولين لا يتمالعكس بل يتم الحجز عادي ويتم الفيض من الاول في الثاني لماذا لا يتم العكس كما في البداية ؟

#13

البنية تعامل كمتغير واحد، أعضاء البنية مرتبين داخلها.

2

هذا الموضوع مغلق.

مواضيع مشابهة