Распределитель по умолчанию С++ - что должно произойти, если размер не равен размеру, переданному при вызове выделения?

20.6.9:

void deallocate(pointer p, size_type n);
  • Требуется: p должно быть значением указателя, полученным из allocate(). n должно равняться значению, переданному в качестве первого аргумента для вызова allocate, который вернул p.
  • Эффекты: Освобождает хранилище, на которое ссылается п.
  • Примечания: Использует ::operator delete(void*) (18.6.1), но не указывается при вызове этой функции.

Что должно произойти, если n не равно значению, переданному в качестве первого аргумента для вызова allocate, который вернул p? Не освобождать? Бросить std::bad_alloc? ...

РЕДАКТИРОВАТЬ: Что я на самом деле имел в виду под "что должно произойти": было бы нормально бросать или утверждать в пользовательской реализации?


person 0xbadf00d    schedule 21.07.2011    source источник


Ответы (3)


Как обычно в стандарте C++, когда ничего не указано явно, нарушение требований приводит к неопределенному поведению. Должен означает всегда должен, это требование, а не опция стандарта C++.

Например, вот что сообщает MSDN:

Указатель _Ptr должен быть возвращен ранее вызовом allocate для объекта распределителя, который сравнивается равным *this, выделяя объект массива того же размера и типа.

это означает, что размер должен точно совпадать, иначе вы столкнетесь с неопределенным поведением.

person sharptooth    schedule 21.07.2011
comment
@FrEEzE — реализация может игнорировать параметр, потому что знает, каким он должен быть. Другие реализации могут использовать его, если сами не помнят размер выделения. - person Bo Persson; 21.07.2011
comment
Игнорирование размера является одним из допустимых видов неопределенного поведения. - person Konstantin Oznobihin; 21.07.2011

Это не говорит. Это означает, что это будет неприятное «неопределенное поведение».

person Bo Persson    schedule 21.07.2011
comment
Да, я знаю. Но я хочу знать, можно ли бросать или утверждать (в пользовательской реализации), когда размер не соответствует выделенному размеру. - person 0xbadf00d; 21.07.2011
comment
Если он не определен, вы можете делать все, что хотите. Стандартные контейнеры обязательно передают правильное значение. Для собственных контейнеров вы можете определить поведение. :-) - person Bo Persson; 21.07.2011

Это присутствует в стандарте, чтобы разрешить базовые распределители, которые не знают размер выделения из своего указателя.

Например, распределитель AmigaOS поддерживает список свободных блоков памяти и даже допускает частичное освобождение (например, если я выделяю 1024 байта, а затем освобождаю 512 байтов по смещению 256, я получаю два выделения по 256 байт), поэтому распределитель ожидает, что я передать эту информацию делокатору.

person Simon Richter    schedule 21.07.2011