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

دالة تجمع عددين و تعيد مؤشر يشير إلى جمعهما

بدأه khaled_prg في 13 أكتوبر 2010 · 38 رد · 2,466 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#27

هناك قاعدة تقول : Never return a reference or a pointer to a local object !

يعني لا تقم بارجاع مرجع او مؤشر على كائن محلي في دالة معينة.


int* S(int a,int b)
{
int* s;
*s = a+b;
return s;
}

في هذه الحالة بعد الخروج من الدالة سيتم تحرير المؤشر , عملية التحرير لا تقوم بحذف المؤشر كليا بل تجعله عبارة عن مؤشر يشير الى شيء غير موجود و بالتالي فان المؤشر الذي سيتم ارجاعه من الدالة سيكون:

invalid pointer !

تم تعديل هذه المشاركة بواسطة xpero في 22 أكتوبر 2010 في 23:00

#28
اقتباس
في هذه الحالة بعد الخروج من الدالة سيتم تحرير المؤشر

كيف يتم تحرير المؤشر و عملية الحجز لم تحدث أصلا ! لأننا أسندنا له قيمة قبل أن نحجز له عنوانا في الذاكرة, يعني إسناد القيمة قبل حجز العنوان هو خطأ يمنع متابعة الترجمة من طرق الكومبايلر, كيف ترد !؟ :)

اقتباس
عملية التحرير لا تقوم بحذف المؤشر كليا بل تجعله عبارة عن مؤشر يشير الى شيء غير موجود و بالتالي فان المؤشر الذي سيتم ارجاعه من الدالة سيكون invalid pointer !

هل تقصد بأن عملية التحرير تكون هكذا دائما أم في هذه الحالة فقط !؟

يعني هل سيتم إعطاء المؤشر العنوان 0X0000 (و في العادة هذا العنوان يكون invalid في اغلب نظم التشغيل لكن ليس دائما وليس في كل الحالات ولكنها حالات نادرة ولن تتعامل معها كمبرمج :) ) مما يعني عدم إمكانية الوصول إلى ذاكرة المؤشر (المُصفر عنوانها) عندها يمكن للنظام أن يعطي هذه الذاكرة لأي برنامج آخر !؟

تحياتي لك :)

#29

انا اخذت الكود الذي كتبته على اساس pseudocode . اما في الحقيقة فذلك الكود لن يعمل لانه تم استعمال المؤشر قبل حجز العنوان.

عملية التحرير لا تحذف المؤشر كليا بل تجعله NULL Pointer .

جرب الكود التالي للتوضيح


#include <iostream>

using namespace std;

int main()
{

int* x =new int;
*x=2;
cout<<"Before delete &x= "<<ios::hex<<x<<endl;//&x=machine dependent
cout<<"Before delete *x= "<<*x<<endl; //*x=2
delete x;
cout<<"After delete &x ="<<ios::hex<<x<<endl;//&x=machine dependent
cout<<"After delete *x ="<<*x<<endl;//*x=0

return 0;
}

#30
اقتباس
عملية التحرير لا تحذف المؤشر كليا بل تجعله NULL Pointer .

تحرير مؤشر ليس له علاقه بجعله NULL Pointer .

الموضوع كله لا علاقه له بحجز ذواكر ، هو يخص سوء تعامل مع الـstack .

اقرأ عن الـStack وكيف تكون الـlocal variables و الـframe .

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#31

GamingMasteR

كيف يمكن لذاكرة محجوزة ديناميكا ان يكون لها علاقة مع ال stack؟(لاحظ اني استعملت new في المثال السابق.)

2- بالنسبة للمثال الذي أعطاه الاخ خالد فالمؤشر الذي سترجع الدالة سيكون invalid لانه بعد الوصول الى نهاية ال local scope الخاص بالدالة سيتم حذف جميع ال automatic variables الخاصة بها ومن بينهم ذلك المؤشر الذي سترجعه الدالة.

---

اذا كانت لديك فكرة حول ميكانيزم تحرير ذاكرة المؤشرات فالمرجوا ان تشرحها لنا :).

كيف سنفسر احتفاظ المؤشر بعنوان المتغير الذي كان يشير اليه حتى بعد ان قمنا بحذفه بواسطة delete؟

#32

المتغيرات التي يتم حجزها باستخدام ال new operator تكون بال Heap وليس ال stack

لا يتم تحرير الذاكره المحجوزه بال Heap اتوماتيكياً (الا في ال manged code مثل ال #C)

المتغير المحجوزه بال stack يتم تحريره بنتهاء ال scope الخاص به

#33
اقتباس
كيف يمكن لذاكرة محجوزة ديناميكا ان يكون لها علاقة مع ال stack؟(لاحظ اني استعملت new في المثال السابق.)

نحن نتكلم هنا عن المؤشر نفسه وليس الذاكرة التي يشير اليها ، بالطبع المؤشر موجود داخل الـStack لأنه Local Variable في حالتنا .

المتغيرات المحلية لا يتم "تحريرها" عند الخروج من الـScope الخاص بالدالة ، بل يتم استخدام Frame مختلف عن طريق زيادة الـStack pointer مما يؤدي الى جعل الـFrame السابق قابل للكتابة عليه عن طريق تعريف متغيرات محلية اخرى في الـParent Routine .

المؤشر سيظل يشير الى ذاكرة صالحة للاستخدام لكنك لا تضمن انه لن يتم الكتابة عليها Overwrite عن طريق حجز متغير محلي آخر .

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#34

@GM

كلامك صحيح بالفعل نظراً للأسئلة التي في النقاش, و لكن أحب أن أضيف أننا يجب أن نعرف(تشديد الراء!) معنى تحرير الذاكرة أولاً. في C, كلامك لا غبار عليه. بينما في ++C, هناك خطوتان واحدة بعد حجز الذاكرة, و واحدة قبل تحريرها real allocation & deallocation. بعد حجز الذاكرة, يتم استدعاء الـ constructor. و قبل تحرير الذاكرة يتم استدعاء الـ destructor. في ++C لا يتم الحديث عن تحرير الذاكرة على أنه الـ deallocation و لكن عن العملية كلها من استدعاء الـ destructor إلى تحرير الذاكرة. لهذا, delete operator لا يمكن عمل overloading كامل له. و إنما يحق لك عمل overloading لعملية الـ deallocation فقط, و أما استدعاء الـ destructor فسيتم استدعاءه دائماً قبل delete. لهذا أيضاً, يمكن أن يقال أن المتغيرات يتم تحريرها بعد الخروج من الـ scope مباشرة في حالة المتغيرات الـ automatic و لكن عملية التحرير نفسها تختلف باختلاف الـ storage specifie

automatic, static, dynamic, extern or register

تحياتي...

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 30 أكتوبر 2010 في 20:10

2
#35
اقتباس
المتغيرات المحلية لا يتم "تحريرها" عند الخروج من الـScope الخاص بالدالة ، بل يتم استخدام Frame مختلف عن طريق زيادة الـStack pointer مما يؤدي الى جعل الـFrame السابق قابل للكتابة عليه عن طريق تعريف متغيرات محلية اخرى في الـParent Routine .

لم أفهم هذه الفقرة :blush: , ما هو الـ Frame !؟

اقتباس
المؤشر سيظل يشير الى ذاكرة صالحة للاستخدام لكنك لا تضمن انه لن يتم الكتابة عليها Overwrite عن طريق حجز متغير محلي آخر .

ماذا تقصد بـ Overwrite !؟

#36

khaled_prg

سأبدأ بالسهلة : overWriting وتعني الكتابة فوق شيئ. او اعادة الكتابة فوق مثل overLoading التي نترجمها باعادة التحميل.

بالنسبة لل Frame فلم افهم جيدا ماذا يريد الاخ GM ان يقصد بها هل عنوان قمَّة ال stack في المسجل ESP ام شيئ اخر.

ال Stack هو بنية من المعطيات تعمل بميكانيزم LIFO او Last In First Out اي آخر عنصر يتم اضافته لل stack يكون هو أول عنصر يتم استرجاعه منه. يمكن تشبيهه بعملية "ترتيب الصحون فوق بعضها"

فاخر صحن يتم اضافته للصف يكون هو اول واحد يتم أخذه لاستعماله.

بعض اضافة او حذف عنصر من stack فانه يتم تسجيل عنوان القمَّّة في الذاكرة داخل المسجل ESP .

#37
اقتباس
بالنسبة لل Frame فلم افهم جيدا ماذا يريد الاخ GM ان يقصد بها هل عنوان قمَّة ال stack في المسجل ESP ام شيئ اخر.

يقصد ان الداله التى تحتوى على المتغير من نوع مؤشر قد انتهى عملها و تم العوده منها ليتم تنفيذ باقى البرنامج، فى هذه الحاله المكان الموجود داخل ذاكرة الـ stack و الذى كان مستخدما من قبل المتغير من نوع المؤشر سيظل محتفظ بالقيمه التى به طالما لم يحدث ان تم استخدام ذلك المكان من قبل داله اخرى.

و الله ولي التوفيق

مدونتي: C++ Tips and Tricks

#38
اقتباس
فى هذه الحاله المكان الموجود داخل ذاكرة الـ stack

هل المؤشر موجود داخل الـ stack !؟

  • البعض يقول نعم, لأنه متغير محلي و الذاكرة التي يشير إليها هي التي توجد في الـ heap ! و لكن كيف يكون المؤشر مُخزن في stack و ذاكرته مُخزنة في الـ heap !؟
  • مالفرق بين تحرير المتغيرات و تحرير المؤشرات و ما آلية عمل كل منهما !؟

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