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

حجز مكان محدد في الheap

بدأه omar_cplusplus في 17 نوفمبر 2008 · 7 رد · 698 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم و رحمة الله و بركاته

دائماً عندما نريد أن نحجز بعض الأماكن في الheap فإننا نأتي بؤشر و نكتب مثل هذا السطر

int *p;
p = (int*)malloc(sizeof(int)*150);

و هكذا سترجع لي دالة malloc مؤشر بالمكان الذي تم حجز فيه هذه المساحة

لكن ما العمل إذا كان عندي مكان محدد أريد حجزه

مثلاً قمت بحجز 150 عدد صحيح كما في الكود السابق

و أريد حجز مثلاً أربعين بايت في المكان التالي

p+150

و بهذا أكون قد جعلت المصفوفة p مكونة من 160 متغير زيادة على ال150 التي حجزتها في السابق

هل يوجد طريقة لذلك ؟؟

تم تعديل هذه المشاركة بواسطة omar_cplusplus في 17 نوفمبر 2008 في 23:37

#2

لا اعلم ان كان هناك طريقه مباشرة أم لا.

لكن من الممكن ان تعمل حجز جديد بالحجم الموسع تنسخ فيه القديم ثم تحذف الحجز القديم.

فيكون لديك ما تريد.

tvquran_6.gif

#3

في هذه الحالة استخدم التابع realloc

void *realloc(void *ptr, size_t size);

لكن كن حذرا , اذا كان ptr==NULL فإن realloc يعمل عمل malloc اما اذا كان size يساوي صفر عندها سيتم تحرير البلوك المحجوز .

تحياتي . . .

llback.jpg

اشهد ان لا إله إلا الله وان محمدا ً رسول الله

#4

السلام عليكم ,,

سؤال جميل أخي العزيز,,

في الحقيقة نظام التشغيل هو المسؤول الرئيسي عن تنظيم الـ Heap, و لذلك عند طلب حجز قطعة من الذاكرة فإن نظام التشغيل يقوم بحجز تلك القطعة و اعطائك العنوان عن طريق الدالة malloc أو حتى new ,,

دوال حجز الذاكرة في ++C/C ما هي إلا تغليف لـ API نظام التشغيل, و لذلك عند ترجمة البرنامج على أكثر من نظام تشغيل تختلف البنية التحتية التي يستخدمها المترجم :)

على العموم ليس علينا كمبرمجي ++C/C الاهتمام بهذا الموضوع, هذا الأمر من اختصاص مبرمجي الأسمبلي في العادة. ( أو حتى إن كنت تريد الاستغناء عن المكتبات القياسية و استخدام API النظام مباشرة و لكن هذا لا ينصح به في الحالات العامة )

بالطبع لكل مشكلة حل :)

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

هذه التقنية تعتبر من المفاهيم المتقدمة قليلاً في إدارة الذاكرة و هذا بالطبع مما تتميز به ++C/C في مرونتها في التعامل مع الذاكرة. (لا أدري إن كان يمكن تطبيق هذا المفهوم في لغات أخرى )

هذه الطريقة في إدارة الذاكرة تسمى Memory Pool, يمكنك البحث عنها و قراءة مقدمة عنها..

تستخدم في الكثير من البرامج "الحقيقة" لأنها توفر كفاءة عالية جداً في حجز و تحرير الذاكرة, و لكن لا ينصح باستخدامها في البرامج التي لا تتعامل مع الذاكرة بكثافة مثل البرامج التي نقوم بتصميمها أنا و أنت عادة و التي تكون مشاريع تعليمية أو صغيرة في الغالب :)

الموضوع متشعب أكثر مما ذكرت, و لكن أرجو أن تكون قد أمسكت بطرف الخيط,,

أبسط أنواع الـ Pools هي الـ Literal Pool,

جميع الثوابت النصية و العددية يتم تخزينها في قطعة واحدة في أماكن متتالية في الذاكرة, ( أتكلم هنا عن const و ليس عن define فالأمر مختلف مع الأخيرة )

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 18 نوفمبر 2008 في 01:17

#5

جزاكم الله خيراً ..

الطريقة التي ذكرها الأخ time1 نفعت مع خطأ بسيط أود أن أكتشف سببه .. و الظاهر أن هناك مشكلة في دالة realloc و ليس خطأً قمت أنا به ...

في البداية قمت بحجز أربعين بايت لأضع فيهم عشر متغيرات من نوع عدد صحيح .. و قمت بوضع بعض القيم فيها

	int *Ptr,i;
	Ptr = (int*)malloc(sizeof(int)*10);
	for (i = 0; i < 10; i++)
	{	Ptr = i;
		printf("%p = %d\n",&Ptr,Ptr);	}

و كان هذا هو الناتج

0x804b008 = 0
0x804b00c = 1
0x804b010 = 2
0x804b014 = 3
0x804b018 = 4
0x804b01c = 5
0x804b020 = 6
0x804b024 = 7
0x804b028 = 8
0x804b02c = 9

ثم قمت بإضافة عشر متغيرات آخرى عليها ..

	realloc(&Ptr[10],sizeof(int)*10);

و لكن قبل أن أضع فيهم القيم قمت بطبع نفس القيم السابقة التي تم حجزها في البداية

	for (i = 0; i < 10; i++)
		printf("%p = %d\n",&Ptr,Ptr);

و كانت النتيجة مختلفة

0x804b008 = 0
0x804b00c = 1
0x804b010 = 2
0x804b014 = 3
0x804b018 = 4
0x804b01c = 5
0x804b020 = 6
0x804b024 = 7
0x804b028 = 8
0x804b02c = 49

تم تغيير آخر قيمة من 9 إلى 49 ..

ثم قمت بإعطاء قيم للمكان الجديد

	for (; i < 20; i++)
	{	Ptr = i;
		printf("%p = %d\n",&Ptr,Ptr);	}

و كانت هذه هي النتيجة

0x804b030 = 10
0x804b034 = 11
0x804b038 = 12
0x804b03c = 13
0x804b040 = 14
0x804b044 = 15
0x804b048 = 16
0x804b04c = 17
0x804b050 = 18
0x804b054 = 19

طبعاً واضح جداً أن أول متغير و هو 0x804b030 يأتي بعد المتغير 0x804b02c الذي تغيرت قيمته من 9 إلى 49 .. ترى ما سبب ذلك التغيير ؟؟

تم تعديل هذه المشاركة بواسطة omar_cplusplus في 19 نوفمبر 2008 في 22:02

#6

هذا السطر خاطئ :

realloc(&Ptr[10],sizeof(int)*10);

غيره الى :

realloc(Ptr,sizeof(int)*20);

بالمناسبة لم اجرب الكود .

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#8

كما قال لك الاستاذ GM السطر يحتوي على خطأ ,

void *realloc(void *ptr, size_t size);

ptr : مؤشر على الغرض الاصلي .

size : الحجم الجديد.

llback.jpg

اشهد ان لا إله إلا الله وان محمدا ً رسول الله

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