لماذا يجب ألا أحاول استخدام القيمة "هذه" بعد "حذف هذا"؟

StackOverflow https://stackoverflow.com/questions/1866461

  •  18-09-2019
  •  | 
  •  

سؤال

في هذه الفقرة من الأسئلة الشائعة C ++ استخدام delete this نوقش البناء. 4 قيود مدرجة.

القيود 1 إلى 3 تبدو معقولة جدا. ولكن لماذا يقيد 4 هناك "يجب ألا يفحصه، قارنه بمؤشر آخر، ومقارنتها ب NULL، أو طباعته، أو إلقاء عليه، أو فعل أي شيء به"؟

انا اعني this هو مؤشر آخر آخر. لماذا لا أستطيع reinterpret_cast ذلك إلى int أو أتصل printf() لإخراج قيمتها؟

هل كانت مفيدة؟

المحلول

السبب الذي لا يمكنك فعل أي شيء به مؤشر بعد حذفه (هذا، أو أي مؤشر آخر)، هو أن الأجهزة يمكن أن تكون (وبعض الآلات القديمة) فخ محاولة تحميل عنوان ذاكرة غير صالح في سجل. على الرغم من أنه قد يكون على ما يرام على جميع الأجهزة الحديثة، فإن المعيار يقول أن الشيء الوحيد الذي يمكنك القيام به لمؤشر غير صالح (غير مهم أو حذف)، هو تعيينه (إما NULL، أو من مؤشر صالح آخر).

نصائح أخرى

إن قيمة "هذا" بعد استدعاء الحذف غير معروفة، وسلوك أي شيء تفعله به هو غير محدد. على الرغم من أنني أتوقع أن يقوم معظم المجال المترجمين بعمل شيء معقول، لا يوجد شيء (في المواصفات) لإيقاف المحول البرمجي من تحديد أن سلوكه في هذه الحالة بالذات سيكون ينبعث من التعليمات البرمجية لتنسيق القرص الثابت. إن استدعاء السلوك غير المحسقل هو خطأ (تقريبا) دائما خطأ، حتى عندما يتصرف مترجمك الخاص بالطريقة التي تريدها.

يمكنك العمل حول هذا من خلال أخذ نسخة من المؤشر (كعدد صحيح) قبل الاتصال حذف.

آها!

3.7.3.2/4: "... يجب أن تلتكل وظيفة الكشف عن التخزين المشار إليه من قبل المؤشر، مما يجعل جميع المؤشرات غير صالحة تشير إلى أي جزء من التخزين المعزول. تأثير استخدام قيمة مؤشر غير صالحة (بما في ذلك تمريرها إلى تخصيص وظيفة) غير محدد ".

لاحظ أن هذا يقول "استخدام القيمة"، وليس "إلغاء تحديد المؤشر".

تلك الفقرة ليست خاصة this, ، ينطبق على أي شيء تم حذفه.

نظرا لأن أي إجراء يمكنك أن تأخذه مع هذا المؤشر قد يؤدي إلى تشغيل المنطق الذي يتم تفسيره على طرق الفصل لهذا الكائن، مما قد يؤدي إلى تعطل.

الآن، يمكن الآن بعض الإجراءات التي تشير إليها عند "آمنة" على ما يبدو، ولكن من الصعب قول ما يحدث في أي طريقة يمكنك الاتصال بها.

من المنشور: "يجب ألا يفحصها، ومقارنتها بمؤشر آخر، ومقارنتها ب NULL، أو طباعتها، أو إلقاءها، فقي بأي شيء معه"؟

يمكن أن تؤدي جميع هذه الإجراءات إلى تشغيل الوظائف المتعلقة بالمشغل، والتي يتم تقييمها بمؤشر غير محدد. Idem للصب.

الآن إذا قمت بإجراء REINTEPRET_CAST، فمن المحتمل أن تكون هناك قصة مختلفة، وربما يمكنك الحصول عليها معك، حيث إعادة تفسير بعض الشيء، دون إظهار بعض الشيء، دون إشراك (بقدر ما أعرف) أي طريقة أخرى.

لنفس الأسباب، فلن تقوم بحذف أي مؤشر آخر ثم حاول وأداء أي عمليات عليه.

ب / ج العنوان الذي يشير إليه الآن، أنه غير محدد، ولا تعرف ما قد يكون هناك ...

في برنامج متعدد الخيوط، في اللحظة التي delete مؤشر، يمكن تخصيص المساحة الحرة موضوع آخر، والكتابة فوق المساحة المستخدمة من قبل this. وبعد حتى في برنامج موضوع واحد، إلا إذا كنت حذرا للغاية حول ما تتصل به من قبل returnجي، أي شيء تفعله بعد delete this يمكن تخصيص الذاكرة والكتابة فوق ما كان يستخدم ل this.

في Microsoft Visual C ++ القابل للتنفيذ المترجمة في وضع التصحيح، deleteيؤدي مؤشر جي إلى الكتابة فوق ذاكرة لها على الفور مع نمط اختبار 0xcc (يتم تهيئة المتغيرات غير المهيمية أيضا مع هذا النمط)، للمساعدة في تحديد أخطاء المؤشر المتدلية مثل هذا واحد.

هذا يذكرني عندما قمت بإصلاح خطأ في لعبة قابلة للتشغيل عبر الإنترنت التي حذف منشئ كائن حريق أقدم حريق إذا وصل العدد الإجمالي للحرائق إلى رقم معين. الحريق المحذوف كان في بعض الأحيان النار الوالد خلق حريق جديد - بام، علة مؤشر تتدلى! كان بسبب الحظ فقط أن هذا الخطأ يتفاعل مع خوارزمية تخصيص الذاكرة بطريقة يمكن التنبؤ بها تماما (تم الكتابة فوق الحريق المحذوف دائما بنيران جديدة بنفس الطريقة) - وإلا فإنه كان سيؤدي إلى إزالة desynchronization بين اللاعبين عبر الإنترنت. لقد وجدت هذا الخطأ عند إعادة كتابة الطريقة التي قامت بها اللعبة بتخصيص الذاكرة. نظرا لقدرة التنبؤ بها، عندما قمت بإصلاحها، كنت قادرا أيضا على تنفيذ مضاهاة سلوكها للتوافق مع عملاء اللعبة القديمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top