Страница 1 из 2

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

Добавлено: 13 ноя 2015, 12:20
Сионист
Можно ли здесь:

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

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

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

new (Item) A (Parametr);
?

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

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

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

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

Подробнее об операторах new, как всегда, можно узнать, поискав в гугле. Первая же статья ведёт на известный С++ ресурс cppreference.

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

Добавлено: 13 ноя 2015, 13:27
Сионист
То есть второй фрагмент уже не умеет бросать исключения. Эйси. А первый? Он то память выделяет.

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

Добавлено: 13 ноя 2015, 13:53
Romeo
В заголовке был вопрос о placement new. Я на него и дал ответ.

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

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

A* Array=(A*)(operator new [](10*sizeof(A), std::nothrow));
И если бы ты открыл приведённую ссылочку из гугла, то, увидев на первой же странице сигнатуры операторов присваивания, сразу же понял, как поправить вызов :) Гугл - это вещь!

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

Добавлено: 13 ноя 2015, 14:42
Сионист
Ваще то открыл. Но:
1. Понял не сразу. Пришлось тестовое приложение писать.
2. Сомнения остались.

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

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

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

Добавлено: 14 ноя 2015, 13:27
Сионист
Вообще то бросается. Обращения к памяти ни как на это не влияют, даже

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

A* Array=(A*)(operator new [](1000000000000*sizeof(A)));
operator delete [](Array);
бросает исключение, но ни один конструктор или деструктор здесь не вызывается в принципе и фактическое обращение к выделенной памяти не происходит.

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

Добавлено: 14 ноя 2015, 13:51
Absurd
Скорее всего имеет место исчерпание адресного пространства. Переходите на x86_64.

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

Добавлено: 17 ноя 2015, 07:26
Сионист
1. Если в x86_64 исчерпывается адресное пространство, то надо переходить с него опять на x86_64? Сам то понял, что сказал?
2. Жалкий триллион интов 16 эксибайт исчерпать не может даже с учётом любых дыр.

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

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

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