#c #map #memory-management
#c #Карта #управление памятью
Вопрос:
Я хочу использовать map
в C , но я не использую исключения. После использования map<int, int> my_map
в функции, как я могу проверить, удалось ли ей выделить память внутри (я понимаю, что с исключениями любой новый внутри, который не может выделить память, выдаст исключение)?
Ответ №1:
Используете ли вы исключения или нет, стандартные контейнеры будут (если они используют свои распределители по умолчанию) выбрасывать std::bad_alloc
, если выделение памяти завершается неудачно. Если вы не поймаете это, ваша программа завершится — так что в этом случае нет способа проверить успех без перехвата исключения.
Если вы действительно хотите устранить исключения (что, на мой взгляд, плохая идея, даже если вы не хотите использовать стандартную библиотеку), тогда вам придется отказаться от стандартных контейнеров, переписав все контейнеры, которые вы хотите использовать, на нестандартную модель распределения, а также проверять и распространять любые сбои. Все стандартные контейнеры предполагают, что распределение будет либо успешным, либо сброшено, поэтому их нельзя использовать с распределителем, который не дает такой гарантии.
Комментарии:
1. Хорошо знать все это. Большое спасибо.
2. Вам не нужна нестандартная модель распределения, поскольку стандарт описывает нестроковую версию
new
оператора. Тем не менее, я не могу использовать стандартную библиотеку.3. @MooingDuck: под «нестандартной моделью распределения» я просто имел в виду что-то, что работает иначе, чем требования к распределителю, указанные стандартной библиотекой контейнеров, а не что-то за пределами языкового стандарта.
Ответ №2:
Используете ли вы исключения или нет, библиотека C использует их для ошибок распределения. Если вы действительно хотите их избежать, вам нужно узнать о распределителях или, по крайней мере, о вашем собственном глобальном операторе new и придумать какую-то другую схему (вызов функции в глобальной переменной?), Когда память недоступна.
Комментарии:
1. Но вы можете указать
nothrow
вnew
, верно? Почему контейнеры не используют его?2. @gruszczy: Что будет делать контейнер в случае ошибки?
3. @gruszczy: стандартные контейнеры не используются
new
; они используют некоторый тип, который соответствует стандартным требованиям распределителя. Одним из этих требований являетсяallocate
функция, которая либо вернет действительный указатель, либо выдаст исключение.4. @gruszczy: что касается почему: исключения являются частью языка и гораздо менее подвержены ошибкам (а также менее навязчивы), чем другие механизмы обработки ошибок, такие как проверка возвращаемых значений функции; вот почему стандартные контейнеры используют их для сообщения об ошибках.
Ответ №3:
Если вы не хотите, чтобы исключения создавались, вы должны написать свой собственный распределитель и использовать его в своей карте : typedef std::map<int, int, std::less<int>, MyAllocator> my_map;
.
Однако вам придется придумать свою собственную внутреннюю логику для обработки ситуаций нехватки памяти, а стандартный интерфейс не предоставляет никакого очевидного интерфейса.
В качестве гибридного решения вы могли бы написать распределитель, который берет память из пула статической памяти и вызывает некоторый глобальный обработчик сбоев, когда он заполнен.
Ответ №4:
Ну, отключенные исключения не являются частью стандарта C , поэтому вы будете использовать поведение, зависящее от компилятора. При этом, по крайней мере, с GCC, оператор по умолчанию new будет, вместо того, чтобы генерировать исключение, если malloc() завершается неудачно, просто прервать программу, если она скомпилирована с -fno-exceptions .