داعيا حذف على متغير المخصصة على المكدس
-
22-07-2019 - |
سؤال
تجاهل أسلوب البرمجة و التصميم هو "آمنة" للاتصال حذف على متغير المخصصة على كومة ؟
على سبيل المثال:
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 في ويندوز ، حصلت على النتائج مثيرة جدا للاهتمام:
داعيا حذف على كومة متغير لا يبدو أن تفعل أي شيء.لا أخطاء في رمي لكن لا يمكن الوصول إلى المتغير دون مشاكل بعد الحذف.
وجود فئة مع الأسلوب مع
delete this
بنجاح حذف الكائن إذا كان يتم تخصيص في كومة ، ولكن ليس إذا كان المخصصة في المكدس (إذا كان في كومة لا يحدث شيء).
لا أحد يستطيع أن يعرف ما يحدث.هذا استدعاء السلوك غير معرف لذلك حرفيا أي شيء يمكن أن يحدث. لا تفعل هذا.
لا، ينبغي حذف الذاكرة المخصصة باستخدام جديدة باستخدام حذف المشغل وينبغي حذف التي خصصت باستخدام malloc باستخدام مجانا. وهناك حاجة لإلغاء تخصيص المتغير الذي يتم تخصيص على كومة.
وملاك يفقد جناحيه ... يمكنك الاتصال فقط delete
على مؤشر المخصصة مع new
، وإلا تحصل سلوك غير معرف.
وهنا يتم تخصيص الذاكرة باستخدام كومة لذلك لا حاجة لحذفه exernally لكن إذا كنت قد allcoted حيوي
ومثل الباحث * و= كثافة العمليات الجديد ()
وبعد ذلك ما عليك القيام به حذف وليس حذف وو(أ نفسه هو المؤشر)، ليتم تخصيص الذاكرة من متجر مجانا.
وأنت أجبت على السؤال بنفسك. يجب استخدام delete
فقط لمؤشرات OPTAINED من خلال new
. القيام بأي شيء آخر غير واضح وبسيط سلوك غير معرف.
لذلك هناك حقا أي قول ما يحدث، أي شيء من التعليمات البرمجية تعمل بشكل جيد من خلال التحطيم لمحو قرصك الصلب هو نتيجة صالحة للقيام بذلك. لذا يرجى <م> أبدا القيام بذلك م>.
وانها UB لأنك يجب أن لا ندعو حذف على عنصر التي لم يتم تخصيصها بشكل حيوي مع الجديد. الامر بهذه البساطة.