Распределитель стека и исключения Hinnant - PullRequest
0 голосов
/ 01 июня 2018

Я хочу использовать распределитель стека Hinnant ( документация , реализация ) в сочетании с контейнерами STL, но я хочу изменить его так, чтобы динамическое выделение памяти НИКОГДА не происходило .

Одна вещь, которая должна быть сделана, чтобы выполнить это, должна заменить вызовы new / delete в методах allocate / deallocate, которые имеют место, если в буфере, предоставленном стеком, нет места.

Нокак я должен иметь дело с исключениями?Контейнеры STL могут выдавать исключения, например

std :: vector :: at

"Функция автоматически проверяет, находится ли n в пределах допустимых элементов в векторе, выбрасываяисключение out_of_range, если оно не [...] "

http://www.cplusplus.com/reference/vector/vector/at/

Я не смог найти четкого ответа, хранятся ли исключения в динамической или статической памяти.Только эти строки дают подсказки:

From [exc.throw] /15.1/4:

Память для объекта исключения выделена неопределенным образом, за исключением случаев, отмеченных в 3.7..4.1.

В заключительной ссылке [basic.stc.dynamic.allocation] / 4 говорится:

[Примечание. В частности, функция глобального распределения не вызывается для выделения хранилища для[...] объект исключения (15.1).- примечание к концу]

https://stackoverflow.com/a/27259902/8007684

Что именно это означает?Зарезервирована ли память для исключений в статической памяти?Или все еще есть какие-либо распределения, происходящие "неуказанным способом", который означал бы, что исключения будут храниться динамически?Приведенное описание занимает много места для интерпретации ...

Итак, мой основной вопрос: Безопасно ли использовать контейнеры STL + распределитель стека Хиннанта, если использование динамической памяти запрещено?Или это не работает, и мне нужно либо использовать -fno-exceptions для замены исключений вызовами abort(), либо реализовать собственные замены контейнеров STL, которые не генерируют исключения ...?

Заранее спасибо!

вдохновляют

1 Ответ

0 голосов
/ 01 июня 2018

Реализации gcc и clang следуют спецификации, называемой Itanium ABI .В ней, между прочим, говорится:

Для хранения исключений требуется хранилище.Это хранилище должно сохраняться во время разматывания стека, так как оно будет использоваться обработчиком и должно быть поточно-ориентированным.Поэтому хранилище объектов исключений обычно выделяется в куче, хотя реализации могут предоставлять аварийный буфер для поддержки выброса bad_alloc исключений в условиях нехватки памяти (см. Раздел 3.3.1).

Память будет выделяться__cxa_allocate_exception подпрограмма библиотеки времени выполнения.Этой подпрограмме передается размер объекта исключения, который должен быть выдан (не включая размер заголовка __cxa_exception), и возвращается указатель на временное пространство для объекта исключения.Он будет выделять память исключений в куче, если это возможно.В случае сбоя при выделении кучи реализация может использовать другие механизмы резервного копирования (см. Раздел 3.4.1).

Если __cxa_allocate_exception не может выделить объект исключения в соответствии с этими ограничениями, он вызывает terminate().

Реализация libc ++ abi __cxa_allocate_exception здесь здесь .Сначала он перейдет в кучу, и если это не удастся, попробуйте буфер аварийного резервного копирования, который статически размещен в libc ++ abi.dylib.Если и куче, и аварийному хранилищу не удается выделить достаточно памяти для созданного пользователем исключения произвольного размера, вызывается terminate().

...