Дружит ли placement new c std::nothrow?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Можно ли здесь:

Код: Выделить всё

Array=(A*)(operator new [](n*sizeof(A)));
запретить исключение?
А здесь:

Код: Выделить всё

new (Item) A (Parametr);
?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Можно узнать зачем...? Как по-мне, ожидать, что они будут "дружить" как минимум, достаточно недальновидно, а если сказать прямо, то глупо.

И так ответ. По умолчанию "не дружит". Точнее, если выражаться общепринятой терминологией, компилятор по умолчанию не генерирует в классе operator new с соответствующей сигнатурой. Причина очень проста. Дело в том, что placement new (в отличие от обычного new) не выделяет память, а значит он и так не может бросить std::bad_alloc. Нам просто нечего запрещать, понимаешь?

Однако, при желании, пользователь может определить такой оператор, если он, например, хочет вложить в оператор с такой сигнатурой какой-то свой тайный смысл.

Подробнее об операторах new, как всегда, можно узнать, поискав в гугле. Первая же статья ведёт на известный С++ ресурс cppreference.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

То есть второй фрагмент уже не умеет бросать исключения. Эйси. А первый? Он то память выделяет.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

В заголовке был вопрос о placement new. Я на него и дал ответ.

В первом фрагменте да, можно. Это ведь не placement new. Будет выглядеть так:

Код: Выделить всё

A* Array=(A*)(operator new [](10*sizeof(A), std::nothrow));
И если бы ты открыл приведённую ссылочку из гугла, то, увидев на первой же странице сигнатуры операторов присваивания, сразу же понял, как поправить вызов :) Гугл - это вещь!
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Ваще то открыл. Но:
1. Понял не сразу. Пришлось тестовое приложение писать.
2. Сомнения остались.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Насколько я понимаю, std::bad_alloc не выбрасывается вообще никогда, так как память на современных операционных системах выделяется ленивым (Lazy) образом после первого обращения по адресу и недостаток оной может проявиться только уже во время работы конструктора объекта. При этом о недостатке памяти твоя программа вообще не узнает, так как ее тихо убьет ядро. В линуксе когда ядро видит что и ОЗУ и своп в общем-то исчерпаны, оно берет все процессы и начисляет им штрафные баллы. Чемпион убивается. Предпочтение отдается жадным пользовательским процессам. Скорее всего это будет какой-нибудь perl запущенный от юзера который из-за кривого регекспа запнулся на кривой строке и ушел перебирать O(N!) комбинаций мемоизируя промежуточные результаты в куче. А вот Оракел с многогигабайтым кешем скорее всего будет амнистирован, так как это серверный процесс. В Windows скорее всего тоже реализована подобная логика, так как других разумных решений подобной проблемы скорее всего не существует.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Вообще то бросается. Обращения к памяти ни как на это не влияют, даже

Код: Выделить всё

A* Array=(A*)(operator new [](1000000000000*sizeof(A)));
operator delete [](Array);
бросает исключение, но ни один конструктор или деструктор здесь не вызывается в принципе и фактическое обращение к выделенной памяти не происходит.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Скорее всего имеет место исчерпание адресного пространства. Переходите на x86_64.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

1. Если в x86_64 исчерпывается адресное пространство, то надо переходить с него опять на x86_64? Сам то понял, что сказал?
2. Жалкий триллион интов 16 эксибайт исчерпать не может даже с учётом любых дыр.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

На win64 верхний предел динамической памяти выделяемой для процесса это 8TB, а не 16 экзабайт. Почему затык на 3TB - вопрос конечно интересный, но не настолько чтобы лезть в msvcrt прямо вот сейчас.

Ну Ок, уговорил, разрешаю тебе ловить std::bad_alloc. Но вот такой вопрос: к примеру, ты компилируешь огромный исходник на С++ с кучей темплейтов и пр. Когда попытался аллокировать память для того чтобы раскрыть какой-то шаблон с новыми параметрами получил внезапно std::bad_alloc. Вопрос: как продолжать дальше работать.
2B OR NOT(2B) = FF
Ответить