Я знаю, что согласно стандарту C++, если новый не сможет выделить память, предполагается, что он будет вызывать исключение std :: bad_alloc. Но я слышал, что некоторые компиляторы, такие как VC6 (или реализация CRT?), Не придерживаются этого. Это правда ? Я спрашиваю об этом, потому что проверка NULL после каждого нового заявления делает код очень уродливым.Будет ли новый возврат NULL в любом случае?
ответ
VC6 был несоответствующим по умолчанию в этом отношении. VC6's new
вернулся 0
(или NULL
).
Вот KB Article Microsoft по этому вопросу вместе с их предложил обходной путь с помощью настраиваемого new
обработчика:
Если у вас есть старый код, который был написан для поведения VC6, вы можете получить такое же поведение с более новыми компиляторами MSVC (например, 7.0 и новее) путем связывания в объектном файле с именем nothrownew.obj
. На самом деле есть fairly complicated set of rules в компиляторах 7.0 и 7.1 (VS2002 и VS2003), чтобы определить, не по умолчанию ли они не бросали или бросали new
.
Кажется, что MS cleaned this up в 8.0 (VS2005) — теперь он всегда по умолчанию использует метание нового, если вы не ссылаетесь на nothrownew.obj
.
Обратите внимание, что вы можете указать, что вы хотите new
вернуть 0
вместо того, чтобы бросать std::bad_alloc
используя std::nothrow
параметр:
SomeType *p = new(std::nothrow) SomeType;
Это, кажется, работает в VC6, так что это может быть способ более или менее механически исправить код, чтобы он работал одинаково со всеми компиляторами, поэтому вам не нужно перерабатывать существующую обработку ошибок.
Основываясь на спецификации C++, он всегда будет бросать std :: bad_alloc, когда вы используете просто новое без параметров, но, конечно, могут быть некоторые несоответствующие компиляторы.
Я бы не закодировал, чтобы быть совместимым с компиляторами, не совместимыми с C++. VC6 является одним из них в этом отношении.
Это хорошая практика, хотя всегда указывайте свой указатель на NULL после их удаления. Поэтому из-за этого проверка NULL по-прежнему необходима.
Это, как говорится, здесь есть пара опций для очистки код:
Вариант 1: Установка собственного нового обработчика
безопасный способ очистить ваш код будет позвонить: set_new_handler первый.
Тогда вы можете проверить NULL в своем обработчике и выбросить std :: bad_alloc там, если возвращается NULL.
Если вам нравятся исключения лучше, то это ваш лучший выбор. Если вам нравится возвращать NULL лучше, вы также можете сделать это, сделав улов внутри вашего нового обработчика.
Вариант 2: Использование перегружен новый
C++ стандартный файл заголовка определяет STRUCT nothrow, который является пустым. Вы можете использовать объект этой структуры внутри new, чтобы получить свою перегруженную версию, которая всегда возвращает 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];
Насколько я понимаю, установка NULL после удаления. Но моя проблема заключается в следующем: int * p = new int; if (p == NULL) { // журнал о сбое распределения памяти. return; } – Naveen
gotcha, обновлено. –
Вы можете бросить bad_alloc в свой новый обработчик, но нет ничего, чтобы проверить NULL. Вы также не можете изменить возвращаемое значение new через обработчик. – 2009-02-15 08:03:11
Я хотел бы добавить несколько (спорное) мнение, что проверка на NULL после попытки выделения в значительной степени упражнения в бесполезности. Если ваша программа когда-либо справляется с этой ситуацией, скорее всего, вы не можете делать гораздо больше, чем быстро выходить. Очень вероятно, что любая последующая попытка распределения также потерпит неудачу.
Не проверяя NULL, ваш следующий код попытается разыменовать указатель NULL, который имеет тенденцию к быстрому завершению работы программы, с относительно уникальным (и легко отлаживаемым) условием выхода.
Я не пытаюсь говорить вам о проверке NULL, это, безусловно, добросовестное программирование. Но вы не получите от этого многого, если только в особых случаях, где вы можете хранить некоторую информацию о восстановлении (без выделения большего объема памяти) или бесплатную менее важную память и т. Д. Но для большинства людей эти случаи будут относительно редкими.
Учитывая это, я просто доверяю компилятору бросить bad_alloc, лично - по крайней мере, в большинстве случаев.
«Код завершен» предлагает предварительно выделить «защитную сетку» памяти, которая может использоваться при работе в ситуациях с нехваткой памяти, чтобы можно было, например, сохранить информацию об отладке до выхода. –
Проблема в том, что на современной VM-системе, если вы придете где-нибудь _near_, закончите (виртуальную) память, вещь будет пейджинговой, так что она будет полностью непригодна. – 2009-02-15 09:58:41
Stefan, zabzonk: больше не могу согласиться. – 2009-02-15 10:30:43
- 1. В любом случае для p.getInputStream() будет «жить»?
- 2. Будет ли новый оператор возвращать NULL?
- 3. Почему в любом случае возврат NA в некоторых случаях
- 4. В любом случае я могу перехватить новый звонок?
- 5. Это в любом случае полезно, если (это! = Null)?
- 6. Выполняется ли IF в любом случае?
- 7. Есть ли в любом случае многомерная карта?
- 8. Возврат null в случае пустого объекта в C#
- 9. В любом случае, чтобы инверсная факториальная функция?
- 10. Flexpaper APIs не будет работать в любом случае
- 11. Phalcon не будет обновлять запись в любом случае
- 12. в любом случае, кроме AsyncTask?
- 13. В любом случае, чтобы заблокировать метод @Produces
- 14. Есть ли в любом случае знать, выпустил ли поток CPU?
- 15. Может ли Gradle помочь решить jar ад в любом случае?
- 16. Возврат null в методе
- 17. И, наконец: гарантируется ли его выполнение в любом случае
- 18. В любом случае, чтобы сократить этот код?
- 19. Есть ли в любом случае время кэширования файла?
- 20. Makefile не проверяет, обновляется ли и компилируется в любом случае
- 21. Будет ли возврат вызова объекта его деструктором?
- 22. Микро-оптимизация, оптимизирована ли она в любом случае современными браузерами?
- 23. Ждать в цикле (в любом случае, в любом случае) в Swift?
- 24. в любом случае писать dll в linux?
- 25. jquery имеет в случае, если инструкция запуска в любом случае
- 26. В любом случае, код C# в Eclipse?
- 27. Получите верхнее число строк в любом случае
- 28. В любом случае упрощения javascript, если else
- 29. backbonejs model.set, событие триггера в любом случае
- 30. В любом случае, чтобы расширить раскадровку.Дети?
Неверные номера версий. Это было нарушено в 5.0 (как говорится в статье, на которую вы ссылаетесь). Это было исправлено в 6.0. –
VC6 по умолчанию также возвращает NULL - я только что протестировал его. Согласно ссылкам «kftdy56f», поведение в VC7 и VC7.1 (VS2002 и VS2003) также может возвращать NULL, в зависимости от того, была ли ссылка libc * .lib или libcp * .lib (CRT или стандартная библиотека C++) в Я не заинтересован в тестировании. –
Чтобы быть справедливым, VC6 был выпущен до того, как был утвержден стандарт C++, что является одной из причин, по которым оно было настолько несоответствующим.Это правда, что стандарт был почти закончен в то время, но нужно помнить, что существуют циклы разработки, и VC6, вероятно, начался по крайней мере годом ранее. –