الشبكة العربية لمطوري الألعاب

محترف مشرف عبد اللطيف حاجي علي مشاركة 31

بتاريخ 23 شباط 2009 08:53 م، قطب انس حاجبيه بشدة وهو يقول:

حسنا ... ادا بما ان التفعيل تم في release mode  فان برنامجك قد يتوقف عن العمل ادا كانت احدى عبارات التي ارسلتها ل  MY_ASSERT خاطئة اما في الحالة العكسية ... فلن يتوقف الرنامج لان MY_ASSERT  لا تقوم بشيئ
دعني أوضح أمرا أو اثنين ☺ . إن الشرط التالي:

#if !NDEBUG
سوف يتحقق في الـ debug وليس في الـ release. حيث أن المعرف NDEBUG و الذي هو اختصار لـ (Not Debug) يعرف في الـ release version عادةً. ولاحظ أنني استخدم عملية الـ Not(!) وبالتالي فإن الشرط السابق يتحقق عندما لا تكون NDEBUG معرفة أي في وضع الـ debug ☺

المشكلة في هذا البرنامج هي أنني طبقت دخلأ معيناً في كلا الحالتين (release و debug). وهذا الدخل نظامي بالنسبة لقواعد البرنامج😒 .
في حالة الـ debug لم يظهر أي خطأ إذ لم يتحقق أي assert وظهر الخرج كما أتوقعه 😄 .
أما في حالة الـ release فمع أنه لم يظهر أي خطأ (تحقق الـ assert لا ينفذ أصلاً في الـ releaseُ) فإن الخرج الذي حصلت عليه لم يكن مماثلاً للذي حصلت عليه في الـ  😲 debug.

أتمنى أن تكون المشكلة قد اتضحت الآن 😄 .
مرة أخرى. ما هو سبب اختلاف الخرج؟ واقترح حلأ مناسباً.

عبد اللطيف حاجي علي
مبرمج
In|Framez

محترف مشرف عبد اللطيف حاجي علي مشاركة 32

وفي 23 شباط 2009 09:33 م، أعرب الشمري عن رأيه بالموقف كالآتي:

ماذا تقصد في الكود التالي :

m_Width = c1 | (c2 << 8

أقصد ماهو عمله ..
هذا الـ code "يجمع" (من concatenate) البايتين c1 و c2 في word واحدة (من حجم 2 بايت). أي لو كان c1=0x54 و c2=0xٍِA8 فإن m_Width سيكون 0xA854 😄
هذه الطريقة مستخدمة بكثرة عندما تقوم بحفظ رقم مكون من أكثر من byte في ملف binary أو ارساله باستخدام الـ socket. حيث تقوم بارسال أول byte أولاً (كما هي حالتنا. وهذا يدعى Little Endian. هناك أيضاً Big Endian encoding حيث ترسل البايت الأخير أولاً) ثم تتبعه بالبايت الذي بعده
وعند فتح الملف (أو استقبال الرسالة) تقوم بتجميع البايتات مرة أخرى في متغير من نفس النوع فينتج لديك الرقم الأصلي ☺

عبد اللطيف حاجي علي
مبرمج
In|Framez

خبير  سلوان الهلالي مشاركة 33

أوجه أصابع الإتهام لهذا السطر:


MY_ASSERT(*itr++ == 1);
 
وهو مذنب! 😄
 
عند الترجمة بإستخدام Debug سوف يتم تنفيذ:

MY_ASSERT(x) 
if (!x) fail(__FILE__, __LINE__);
بالتالي زيادة واحد إلى itr (++), أي بشكل فعال الإنتقال للعنصر القادم.
 
في حالة Release:

MY_ASSERT(x) // Nothing
سوف يتم إستبدال السطر بالكامل بالتعليق, من دون النظر إلى محتوى x, لذلك لن يتم زيادة واحد إلى itr, أي لن يتم الإنتقال للعنصر القادم.
 
إثبات آخر إن من يود إستخدام الـ Macros يجب عليه إما إستخدامها بحذر أو تجنب إستخدامها بالكامل. 😏

خبير مشرف مؤيد مارديني مشاركة 34

شكراً عبد اللطيف على هذه الأفكار الرائعة!
استفدت من كثير منها من حيث "الفكر البرمجي"، فلست من مردة ++C كما تعلم P:
سأكتفي بالمتابعة، وربما المشاركة في حال طرحت أفكار عن #C مرة أخرى.

تحياتي!

Moayad Mardini,
MSDN Forums Moderator

محترف مشرف عبد اللطيف حاجي علي مشاركة 35

أصبت أخي سلوان. حيث أن الـ code السابق يرتكب خطأ جسيماً هو أن التحقق له آثار جانبية (زيادة المتغير itr 😲 ). وأنت على حق تماماً: إذا كنت تريد استخدام الـ macros فاستخدمها بحذر أو دعك منها ☺ .

لكنك لم تقترح حلاً! على كل هذا أفضل لي إذا أنه يتيح لي أن أطرح سؤال محيراً جديداً 😄 . لكني منذ الآن (وبناء على اقتراح إدارة الموقع) سأقوم بتخصيص موضوع منفصل لكل سؤال وذلك لسهولة قراءة الأسئلة مع حلها والسماح بالمناقشة حتى بعد اعتبار السؤال منتهياً ☺ .
لذلك يمكنكم متابعة الموضوع في الموضوع الجديد: “مشاكل برمجية محيرة: assert ”
http://www.agdn-online.com/communities.aspx?view=posts&threadid=532

عبد اللطيف حاجي علي
مبرمج
In|Framez

محترف مشرف عبد اللطيف حاجي علي مشاركة 36

كي تكون هذه المناقشة مكتملة. أحب أن أنوه إلى خطأ ثان في تعريف MY_ASSERT. يمكنك أن تقرأ عن هذا الخطأ بالتفصيل في الموضوع المنفصل: "مواضيع برمجية محيرة: assert"

http://www.agdn-online.com/communities.aspx?view=posts&threadid=532

عبد اللطيف حاجي علي
مبرمج
In|Framez