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

أخترنا لك(5): ﻻتخلط بين استخدام delete و delete[] .

بدأه محمد عودة في 12 سبتمبر 2012 · 5 رد · 1,370 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

مرحبا بكم في أخترنا لك(5)

الفهرس الرئيس لــ سلسلة أخترنا لك فى سي++

أخترنا لك(5) : ﻻتخلط بين استخدام delete و delete[] .

هناك عادة شائعة بين المبرمجين ﻻ ادري اين مصدريها تقول ممكن ان نستخدم الكلمة المحجوزة delete بدﻻ من delete[] لتحرير مساحة الذاكرة الديناميكية المحجوزة للمصفوفة من انواع البيانات اﻻساسية فى محبوبتى سي++. مثال

int *p = new int[10];
delete p;
// خطأ يجب ان تكون delete[] p

طبعا العادة او التقليد السابق خاطئ تماما. ﻻن مواصفات سي++ القياسية تقول ان استخدام delete لتحرير اى مساحة ذاكرة محجوزة ديناميكيا لمصوفة من احد اﻻنواع اﻻساسية هو سلوك غير مُعرف undefined behavior اى ان اللغة لم تضع لة مقياسا وبالتالى النتائج المترتبة على تكون خطيرة. والحقيقة ان فى بعض نظم التشغيل البرامج التى تستخدم delete بدﻻ من delete[] ﻻتسبب انهيار للبرنامج او قد تكون متروكة للحظ وانت نصيبك يعني ممكن البر نامج ينهار او يعمل بشكل يبدو صحيح. كمثال فى المترجم فجوال سي++ يدعم كلا من delete و delete[] للأنواع اﻻساسية باستدعاء الدالة free() ومع ذلك ﻻ توجد اي ضمانات ان النسخ المستقبلية من فيجوال سي++ سوف تدعم هذة الميزة باﻻضافة الى ذلك المشاكل الناتجة عن تشغيل الكود على مترجم آخر .

والخلاصة ان استخدام delete بدﻻ من delete[] او العكس بالعكس شئ خطير ويجب علينا تجنية.

وتصحيح الكود السابق هو:

delete[] p;

هل يذكر احدكم شئ عن العادات الغير معرفة فى سي++ ؟ التى يظن البعض انها صحيح.

تم تعديل هذه المشاركة بواسطة محمد عودة في 17 سبتمبر 2012 في 09:29

3

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#2

أجل, هذا النوع من الأغلبية يقع فيه, خطأ سلوك غير معروف

سلوك غير معروف لكود معين يعني أن النتيجة غير متوقعة و يمكن تسبب كراش للبرنامج

مثلا

int func(int x){
if(x==10)
 return 10*2;
}

main(){
printf("%d", func(11));
}

الدالة func يمكن أن تصل الى نهايتها بدون أن تعيد أي شيء,

النتيجة

1768647031
2

[سبحان الله و بحمده, سبحان الله العظيم]

#3

أخي @محمد ..

اقتباس
هناك عادة شائعة بين المبرمجين ﻻ ادري اين مصدريها تقول ممكن ان نستخدم الكلمة المحجوزة delete بدﻻ من delete[] لتحرير مساحة الذاكرة الديناميكية المحجوزة

ما الفرق بينهما ... يعني ماذا تعمل كل منهما ؟؟

أخي @ياسين ..

اقتباس
الدالة func يمكن أن تصل الى نهايتها بدون أن تعيد أي شيء,

هنا يصدر المترجم رسالة تحذير warning مفادها (ليس جميع المنافذ في الدالة تعيد قيمة !!!)

أخي @محمد ..

اقتباس
هل يذكر احدكم شئ عن العادات الغير معرفة فى سي++ ؟ التى يظن البعض انها صحيح.

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

هل يمكنكم اكتشافه ؟أو حتى توقع المخرجات ... سيصيبكم بصدمة تحسسية ..هذا أكيد ..laugh.giflaugh.gif...ممنوع استخدام الcompilerwink.gif

#include<cstdio>
int main()
{
unsigned a=10,i=0;
for(;i>=0;i--)
printf("%u\n",a--);
return 0;
}

تحياتي ... وشكراً لك أخ @محمد..

1
#4

مصطفى, i صرحت عنها unsigned, الحلقة ما راح تنتهي لان i مش راح تكون اقل من الصفر

1

[سبحان الله و بحمده, سبحان الله العظيم]

#5

بداية اشكرك على التنسق الجميل فى طرح الاسئلة وخصوصا : @ محمد

اقتباس
ما الفرق بينهما ... يعني ماذا تعمل كل منهما ؟؟

شوف أخى @مصطفى:

عندما تستخدم الكلمة المحجوزة new فى حجز ذاكرة ديناميكية تسمي heap فأنت :

  • أم أن تحجز ذاكرة لمتغير واحد أو كائن واحد مثالا على الترتيب:
int *pn = new int;
Cobj *pcobj = new Cobj;


انت حجزت ذاكرة الآن لابد من حذفها بعد ان تنتهي من استخدامه ونستخدم كلمة delete :

delete pn;
	delete pcobj

;

  • أم ان تحجز مصفوفة فى الذاكرة الديناميكية كما يالى

	int *pn = new int[10];
	Cobj *pcobj = new Cobj[10];

الحذف بأسخدام delete[] :

	delete [] pn;
	delete [] pcobj;

  • أذا فأن delete تسخدم لحذف متغير واحد او كان واحد تم حجزة ديناميكا
  • أم delete[] فتستخدم لحذف مصفوفة بكاملها من الذاكرة تم حجزها ديناميكيا

الكود كامل للأستذادة:

#include <iostream>
using namespace std;
class Cobj
{
public:
	Cobj(){}
};
int main(){
	int *pn = new int;
	Cobj *pcobj = new Cobj;	

	delete  pn;
	delete pcobj;

	int *pnArray = new int[10];
	Cobj *pcobjArray = new Cobj[10];	

	delete [] pnArray;
	delete [] pcobjArray;
	return 0;
}

أخى @مصطفى

اقتباس
#include<cstdio>
int main()
{
unsigned a=10,i=0;
for(;i>=0;i--)
printf("%u\n",a--);
return 0;
}

هذا الكود لا يحوي سلوك غير معرف انة يحوي أخطاء فى لغة تطبيق قواعد لغة البرمجة سي++ .

يعمل بشكل لا نهائي ... اى لن يتحقق شرط توقف الدوارة for وايضا unsigned بدون نوع المتغير الخ

تم تعديل هذه المشاركة بواسطة محمد عودة في 12 سبتمبر 2012 في 20:07

1

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#6
اقتباس

  • أذا فأن delete تسخدم لحذف متغير واحد او كان واحد تم حجزة ديناميكا
  • أم delete[] فتستخدم لحذف مصفوفة بكاملها من الذاكرة تم حجزها ديناميكيا

تمام .. واضح جزاك الله خيراً ... فكرة مهمة .. أستغرب عدم تداركها في كثير من المراجع والكتب العربية !!!

اقتباس
بداية اشكرك على التنسق الجميل

جزى الله عنّا @أحمد الشنقيطي ما هو أهله ...laugh.gif

@ياسين ... أحسنت .. استغرقت معي ربع ساعة ضمن كود كبير جداً حتى فهمت أنها سبب المشكلة المززززعجة dry.gif

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 12 سبتمبر 2012 في 20:09

1

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