سؤال

أعلم أنه وفقا لمعيار C ++ في حالة فشل جديد في تخصيص الذاكرة من المفترض أن يرمي استثناء STD :: BAD_ALLOC. لكنني سمعت أن بعض المحامرة مثل VC6 (أو تنفيذ CRT)) لا تلتزم به. هل هذا صحيح ؟ أنا أسأل هذا لأن التحقق من خالية بعد كل بيان جديد يجعل الرموز تبدو قبيحة للغاية.

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

المحلول

كان VC6 غير متوافق بشكل افتراضي في هذا الصدد. VC6. new عاد 0 (أو NULL).

إليك مقال Microsoft KB في هذه المشكلة مع الحل البديل المقترح باستخدام مخصص new معالج:

إذا كان لديك رمز قديم تم كتابته لسلوك VC6، فيمكنك الحصول على نفس السلوك مع تحديثات MSVC الجديدة (شيء مثل 7.0 والإصدارات الأحدث) من خلال الارتباط في ملف كائن باسم nothrownew.obj. وبعد هناك في الواقع مجموعة معقدة إلى حد ما من القواعد في 7.0 و 7.1 التحويل البرمجيات (VS2002 و VS2003) لتحديد ما إذا كانوا يتخللون عن عدم الرمي أو الرمي new.

يبدو أن تنظيف السيدة هذا في 8.0 (VS2005)، كما أنه يقيم دائما إلى رمي جديد إلا إذا كنت ترتبط بالتحديد nothrownew.obj.

لاحظ أنه يمكنك تحديد أنك تريد new لكي ترجع 0 بدلا من رمي std::bad_alloc باستخدام std::nothrow معامل:

SomeType *p = new(std::nothrow) SomeType;

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

نصائح أخرى

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

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

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

بالنظر إلى هذا، أود فقط أن أثق بالمترجم لرمي bad_alloc، شخصيا - على الأقل في معظم الحالات.

بناء على المواصفات C ++، فإنه سوف يرمي دائما STD :: BAD_ALLOC عند استخدام عادي جديد مع عدم وجود علامات، ولكن بالطبع يمكن أن يكون هناك بعض التحويل البرمجيات غير المتوافقة.

لن أكون مكتظا مليئا بالمجمعات المترجم المتوافقة مع غير C ++. VC6 كونها واحدة منهم في هذا الصدد.

من الممارسات الجيدة أن تحدد دائما مؤشرك إلى NULL بعد حذفها. لذلك بسبب ذلك، لا تزال هناك حاجة للتحقق من عدم وجود NULL.

التي يقال، إليك خيارات زوجين لتنظيف الكود الخاص بك:

الخيار 1: تعيين معالج جديد الخاص بك

طريقة آمنة لتنظيف الكود الخاص بك ستكون الاتصال بما يلي: set_new_handler. أول.

ثم يمكنك التحقق من NULL في معالجك ورمي STD :: BAD_ALLOC هناك إذا تم إرجاع NULL.

إذا كنت تحب الاستثناءات بشكل أفضل، فهذا هو أفضل رهان. إذا كنت ترغب في إرجاع NULL بشكل أفضل، فيمكنك أيضا القيام بذلك عن طريق القيام بالقبض داخل معالجك الجديد.

الخيار 2: استخدام جديد overloaded جديد

يعرف ملف الرأس القياسي C ++ بتهوية غير فارغة. يمكنك استخدام كائن من هذه الهيكل داخل جديد للحصول على إصدار التحميل الزائد الذي يقوم دائما بإرجاع NULL.

void* operator new (size_t size, const std::nothrow_t &);
void* operator new[] (void *v, const std::nothrow_t &nt);

لذلك في التعليمات البرمجية الخاصة بك:

 char *p = new(std::nothrow) char[1024];

هنا فاصل جيد لمزيد من القراءة

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