سؤال

تجاهل أسلوب البرمجة و التصميم هو "آمنة" للاتصال حذف على متغير المخصصة على كومة ؟

على سبيل المثال:

   int nAmount;
   delete &nAmount;

أو

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
هل كانت مفيدة؟

المحلول

لا, أنها ليست آمنة للاتصال delete على كومة تخصيص متغير.فقط delete على الأشياء التي تم إنشاؤها من قبل new.

  • لكل malloc أو calloc, ينبغي أن يكون هناك واحد بالضبط free.
  • لكل new يجب أن يكون هناك واحد بالضبط delete.
  • لكل new[] يجب أن يكون هناك واحد بالضبط delete[].
  • لكل تخصيص مكدس, يجب أن يكون هناك صريحة تحرير أو حذف.المدمر يسمى تلقائيا ، حيثما ينطبق ذلك.

بشكل عام, لا يمكنك مزيج المباراة أي من هذه ، على سبيل المثاللا free-ing أو delete[]جي new الكائن.وبذلك النتائج في السلوك غير معرف.

نصائح أخرى

حسنا، دعونا نحاول فيه:

jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault

وهكذا يبدو أنها ليست آمنة على الإطلاق.

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

عند محاولة تحرير أي الذاكرة التي لم تحصل عليها من جديد، تلك المعلومات مسك الدفاتر لن يكون هناك ولكن النظام سوف يتصرف وكأنه هو والنتائج ستكون غير متوقعة (سيئة عادة).

نعم، هو سلوك غير معرف: عابرة إلى delete أي شيء لم يأت من new وUB:

<اقتباس فقرة>   

ومستوى C ++، قسم 3.7.3.2.3:   قيمة الوسيطة الأولى التي تزود بها واحدة من وظائف إلغاء تخصيص ثيا المقدمة في المكتبة القياسية قد تكون قيمة null المؤشر. إذا كان الأمر كذلك، وإذا كانت وظيفة إلغاء تخصيص واحدة المتوفرة في المكتبة القياسية، والدعوة إلى وظيفة إلغاء تخصيص له أي تأثير. خلاف ذلك، يجب أن تكون القيمة المقدمة إلى operator delete(void*) في المكتبة القياسية واحدة من القيم التي يتم إرجاعها من قبل الطلب السابق إما operator new(std::size_t) أو operator new(std::size_t, const std::nothrow_t&) في المكتبة القياسية.

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

بعد ان لعب قليلا مع g + + 4.4 في ويندوز ، حصلت على النتائج مثيرة جدا للاهتمام:

  1. داعيا حذف على كومة متغير لا يبدو أن تفعل أي شيء.لا أخطاء في رمي لكن لا يمكن الوصول إلى المتغير دون مشاكل بعد الحذف.

  2. وجود فئة مع الأسلوب مع delete this بنجاح حذف الكائن إذا كان يتم تخصيص في كومة ، ولكن ليس إذا كان المخصصة في المكدس (إذا كان في كومة لا يحدث شيء).

لا أحد يستطيع أن يعرف ما يحدث.هذا استدعاء السلوك غير معرف لذلك حرفيا أي شيء يمكن أن يحدث. لا تفعل هذا.

لا، ينبغي حذف الذاكرة المخصصة باستخدام جديدة باستخدام حذف المشغل وينبغي حذف التي خصصت باستخدام malloc باستخدام مجانا. وهناك حاجة لإلغاء تخصيص المتغير الذي يتم تخصيص على كومة.

وملاك يفقد جناحيه ... يمكنك الاتصال فقط delete على مؤشر المخصصة مع new، وإلا تحصل سلوك غير معرف.

وهنا يتم تخصيص الذاكرة باستخدام كومة لذلك لا حاجة لحذفه exernally لكن إذا كنت قد allcoted حيوي

ومثل الباحث * و= كثافة العمليات الجديد ()

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

وأنت أجبت على السؤال بنفسك. يجب استخدام delete فقط لمؤشرات OPTAINED من خلال new. القيام بأي شيء آخر غير واضح وبسيط سلوك غير معرف.

لذلك هناك حقا أي قول ما يحدث، أي شيء من التعليمات البرمجية تعمل بشكل جيد من خلال التحطيم لمحو قرصك الصلب هو نتيجة صالحة للقيام بذلك. لذا يرجى <م> أبدا القيام بذلك .

وانها UB لأنك يجب أن لا ندعو حذف على عنصر التي لم يتم تخصيصها بشكل حيوي مع الجديد. الامر بهذه البساطة.

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