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

Delete مع Null Pointer

بدأه MohammadKaraki في 2 أغسطس 2009 · 8 رد · 870 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

هذه معلومة صغيرة أحببت مشاركتكم بها,,

وهي عن عبارة الشرط الشائعة بين المبرمجين, على فرض أن p هو مؤشر

if( p )
	 delete p;

باعتقادهم أن حذف مؤشر قيمته NULL ستسبب Crach للبرنامج ومن ثم غلقه,,

لكن هذا ليس صحيحا, C++ تضمن لك أن لا يحدث شيئاً إذا قمت بحذف مؤشر للقيمة 0 أو NULL

هذا كل شيء, أرجو أن تكون معلومة مفيدة,,

والسلام عليكم

SAFETY TIP : Always delete what you new, and free what you malloc, never mix new with free or malloc with delete.

#2

السلام عليكم ...

كلام سليم :)

بالفعل كنت أكتب delete بهذه الطريقة, حتى رأيت سؤالاً في Stackoverflow حول هذه النقطة, و الذي يظهر أن المواصفات القياسية لـ ++C تستوجب على كاتب الـ implementation الخاص بـ delete أن يتم التحقق من كونه لا يساوي null.

تحياتي ..

#3

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

جميل ، شكرا لك أخي محمد ...

لدى اضافة بسيطة عن الnull pointer وهي أنك يمكن أن تستدعي من خلاله دالة عادية من داخل كلاس .. لاحظ المثال التالي:

#include <iostream>
using namespace std; 

class Test {
	public :
		void go() {
			cout << "hello Null Pointer" << endl;
		}

		//int x;
};

int main () {
	Test* test = NULL;
	test->go();

	//test->x = 10;

	return (0);
}

الأن سيعمل البرنامج ويطبع العباره ..

قم بحذف التعليقات ، وشغل البرنامج وسيحصل crash .. أيضا اذا كانت دالة virtual سوف يحدث كراش ..

من يملك التفسير :wink: ؟

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

#4

السلام عليكم ...

اقتباس
من يملك التفسير ؟

كود الـ class نفسه سيكون في الذاكرة. بمعنى آخر, كود جميع دوال الصنف موجودة حتى و لو لم يكن هناك كائنات منشأة من هذا الصنف.

في هذا السطر :

test->go();

سيتم تمرير عنوان الكائن عن طريق المؤشر this, في الدالة go, بالطبع كائننا عبارة عن التالي :

Test* test = NULL;

أي انه لا يوجد كائن "حقيقي", بالتالي سيتم تمرير العنوان NULL كمؤشر إلى الدالة go.

و لكن مع هذا السطر :

test->x = 10;

فأنت تقوم بعمل dereferencing لأربع bytes بداية من NULL. بالتالي يحصل الـ crash :)

عموماً, عملية dereferencing لأي مؤشر يشير إلى NULL, عملية غير معرفة في قوانين اللغة نفسها, بالتالي من الممكن أن يكون هناك crash و من الممكن أن لا يكون, هذا يعتمد على الـ environment التي يعمل فيها البرنامج و المترجم نفسه.

تحياتي ..

#5

:clapping:

نعم النقطه المهمه عندما نقوم باستدعاء اي دالة عضو member function وهي أن يكون هناك معامل خفى مرسل للدالة ( وهو this) يمثل لنا عنوان الكائن الذي استدعى الدالة ،، وعندما قمنا باستدعاء الدالة go (وكان this == null) فتمت الطباعه لأنه لم يحصل أي وصول لبيانات الكائن Referencing .. أما في الحالة الأخرى فحصل Access Violation والسبب أننا وصلنا لمنطقة محظورة وهنا سوف يحصل Crash للبرنامج وتتوقف العملية من العمل Terminating the process .

في أنظمه ويندوز أي برنامج (عملية ) تقسم أربعه أقسام كما في الصوره :

post-51148-1249205332_thumb.png

لنركز الأن على السطر الأول وهو قسم الNULL Pointer أيضا نركز على العموم الأول (أنظمه x86) ، هذا القسم يبدأ من العنوان 0x00000000 الى 0x0000FFFF وهو يساعد المبرمجين على كشف التعامل مع المؤشرات الخاليه NULL-Pointer فاذا أحتوي الThread داخل العملية Process على عملية قرائه أو كتابة لأي عنوان في هذه المنطقه بالكامل سوف تكون النتيجه هي Access Violation .

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

post-51148-1249205487_thumb.png

فإذا لم تستطع الدالة malloc ايجاد مساحة كافيه في الذاكرة فسوف ترجع NULL والكود السابق لم يتحقق من ذلك وأفترض أن الناتج هو صحيح دائماً ، وفي حال عادت الدالة بالقيمه NULL فالسطر الثاني سوف يحاول الوصول للعنوان 0x00000000 لكي يضع القيمه 5. وبما أن هذا العنوان داخل المنطقه الأولى NULL-Pointer فسوف تصدر خطأ Access Violation ويتم انهاء العملية Process Terminate .

هكذا تكون هذه المنطقه مساعده للمبرمجين وتريحهم من عمل error-checking للقيم الراجعه من دوال الذاكرة وتصدر خطأ واضح عن حدوث مشكلة ما وبالتالي كما ذكرنا تساعد المبرمجين على ايجاد الأخطاء في التطبيقات. ولا يمكن حجز مساحه في تلك المنطقه وحتى باستخدام دوال الذاكرة Win32 Memory Management API ...

(من موضوع الVirtual Memory الذي سيطرح قريبا في الأسواق :P ) .

بالتوفيق :) ..

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

#6

السلام عليكم ..

جميل يا وجدي :)

بالفعل مادام هناك اتصال ببيئة البرنامج لابد من التحقق من الأخطاء دائما... هذه في ++C للفائدة :

post-89451-1249206718_thumb.png

البعض يعتقد أن الـ exception يحصل فقط لو أن الحجم المطلوب غير متوفر و لكنه يستبعد الموضوع, لأن الذواكر هذه الأيام كبيرة جداً, لكن يتم نسيان أن هذه الحالة واردة, خصوصاً لو أن الذاكرة مبعثرة fragmented.

بالمناسبة المواضيع التي تكتبها لدي في المفضلة, أنا في انتظار انتهاء الاختبارات "النصف" صيفية, هلكونا في الحر :lol:

خصوصاً موضوع الـ ternary tree :) سأحاول كتابتها مع محاكاة STL إن شاء الله. و في انتظار الموضوع الجديد :wink:

تحياتي ...

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 2 أغسطس 2009 في 12:54

#7
اقتباس
من موضوع الVirtual Memory الذي سيطرح قريبا في الأسواق
اقتباس
خصوصاً موضوع الـ ternary tree سأحاول كتابتها مع محاكاة STL إن شاء الله. و في انتظار الموضوع الجديد

^^

عروض الصيف:lol: ,

بارك الله فيكم .. معلومات جديدة .. وغريبة بنفس الوقت ! .. أما بالنسبة للموضوع الاصلي الذي طرحه الاخ محمد , فأعلم ذلك .. أعلم أنه غير الزامي .. لكن أقوم بذلك كأي مبرمج يبحث عن الأمان .. أو أنه موسوس قليلاً :-) .

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#8

الأخ خالد لا يزال يعمل بالظلام :D

جملة new أضعها داخل try إذا كانت الكمية مخيفة قليلا,,

فلا أظن أن هناك حاجة لوضع تعليمة الحجز (new) داخل بلوك try عند حجز كميات قليلة من الذاكرة (عدة بايتات),

وحتى لو كانت الذاكرة مبعثرة فلن تكون عملية حجز عدة بايتات عملية خطرة!

تم تعديل هذه المشاركة بواسطة MoHammaD_93 في 4 أغسطس 2009 في 00:55

SAFETY TIP : Always delete what you new, and free what you malloc, never mix new with free or malloc with delete.

#9
اقتباس
أيضا اذا كانت دالة virtual سوف يحدث كراش ..

لأن دوال الvirtual يتم إنشاء المؤشرات لها وقت تكوين الكائن ... وبالتالي عندما لا يكون هناك إنشاء للكائن ... سيكون المؤشر لا يشير إلى شئ وسيحدث الخطأ ..

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