Является ли С++ новой памятью в физической оперативной памяти после выделения?

new[] дает нам последовательную память.

C++23 проект N4928, глава 6.7.5.5.2 (2) «Функции распределения», выделение мое:

Функция распределения пытается выделить запрошенный объем памяти. В случае успеха он возвращает адрес начала блока памяти, длина которого в байтах не меньше запрошенного размера.

Указывает ли спецификация C++, находится ли этот блок памяти на самом деле в физической оперативной памяти после выделения, или он может находиться только в виртуальной оперативной памяти и, таким образом, полностью или частично выгружаться на диск?

Origin of this question is a discussion in the comments of this question.

Обычно различие между виртуальной и физической памятью не происходит на уровне приложения, поэтому я был бы удивлен, если бы это вообще обсуждалось в проекте C++.

500 - Internal Server Error 30.07.2024 11:01

Ничто в стандарте C++ не указывает на это. У него очень абстрактное представление об аппаратном обеспечении. Однако, основываясь на недавних вопросах, я могу сказать, что на практике память, возвращаемая new, может находиться в виртуальной памяти. Кроме того, «в виртуальной памяти» не означает «выгружено на диск», по крайней мере, в Windows.

john 30.07.2024 11:01

Стандарт C++ нацелен на Абстрактную машину, которая не заботится о физической/виртуальной памяти. «...Семантические описания в этом документе определяют параметризованную недетерминированную абстрактную машину. Этот документ не предъявляет никаких требований к структуре соответствующих реализаций. В частности, им не нужно копировать или эмулировать структуру абстрактной машины. Скорее, соответствующие реализации являются требуется эмулировать (только) наблюдаемое поведение абстрактной машины, как описано ниже...».

Richard Critten 30.07.2024 11:07

Где на самом деле расположена память, зависит от ОС, а не от самого C++.

Pepijn Kramer 30.07.2024 11:17

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

Thomas Weller 30.07.2024 11:18

А когда дело доходит до ОС, Linux может при обстоятельствах согласиться даже на необоснованное распределение, которое невозможно удовлетворить, используя всю доступную память. Распределение, похоже, будет успешным, вы получите кучу нерезидентных страниц, и ваша программа будет уничтожена позже, только если она попытается записать слишком много из них.

teapot418 30.07.2024 11:20

Также помните, что некоторые ОС и/или оборудование даже не поддерживают виртуальную память, и ваш код C++ будет выглядеть так же. Меня больше интересует, почему вы хотите это знать? Это из-за каких-то проблем с производительностью или просто из любопытства? :)

Pepijn Kramer 30.07.2024 11:20

@PepijnKramer: это в основном из-за нового комментария Питера, в котором говорится, что два std::vector (старый вектор до перераспределения и новый вектор) должны оба находиться в оперативной памяти. Сомневаюсь.

Thomas Weller 30.07.2024 11:24

Определенно было бы более эффективно иметь оба варианта в физической оперативной памяти одновременно. Но AFAIK, это не то, как работает подкачка памяти: если есть ошибка страницы, страница заменяется другой страницей (в соответствии с некоторой стратегией)... так что вполне может быть, что после копирования оба вектора находятся в ОЗУ (если ОЗУ достаточно большая ). Таким образом, копирование может замедлиться до такой степени, что его станет невозможно использовать из-за уничтожения... но пока достаточно виртуальной памяти, я не понимаю, почему копирование не удастся. (Но опять же, то, как это действительно работает, зависит от ОС)

Pepijn Kramer 30.07.2024 11:32

@ThomasWeller они не обязательно должны быть оба в физической оперативной памяти. Питер здесь неправ. Они оба должны помещаться в свободном адресуемом пространстве, которым обычно является адресуемая пользователем виртуальная память, но это не обязательно. В том примере DOS, который вы упомянули, в модели крошечной памяти std::vector не сможет изменить размер, прежде чем он достигнет размера даже 32 КБ, хотя его max_size(), вероятно, укажет 64 КБ максимального полезного пространства.

Andrey Turkin 30.07.2024 12:55
stackoverflow.com/a/24631743/17034
Hans Passant 30.07.2024 13:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
113
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

C++ на самом деле не имеет дело с физическими машинами. Он нацелен на некую абстрактную машину, имеющую некую унифицированную память. В стандарте C++ не существует таких понятий, как физическая или виртуальная память, поэтому он не может указывать ни один из способов. Итак, это ответ на ваш вопрос, как он задан.

Теперь, если бы вы спросили: «Будет ли моя новая [] выделенная память в реальности выделена в физической памяти?», ответ будет: «Это зависит от среды». Например, ваша программа на C++ может быть нацелена на какой-нибудь микроконтроллер, например ARM Cortex M3, у которого нет MMU. В этом случае new[] предоставит вам кусок непрерывной физической памяти по указанному вам адресу (и там вообще нет понятия виртуальной памяти, поэтому ваш вопрос не имеет смысла в этой среде). Вы можете настроить DOS, и в этом случае вы также получите непрерывную физическую память по указанному вам адресу (если только ваша программа не работает под каким-либо VDM, например, в Windows, и в этом случае она не получает физическую память). Вы можете настроить таргетинг на какую-нибудь ОС с MMU, но без подкачки или распределения по требованию. В этом случае вы получите непрерывную виртуальную память, поддерживаемую физической памятью, но эта физическая память может не быть непрерывной, и вы не будете знать ее адрес. Наконец, вы можете ориентироваться на какую-нибудь «обычную» среду ОС с MMU и подкачкой, например Linux — и в этом случае вы получите виртуальную память, которая может не поддерживаться физической памятью (в случае Linux, в котором есть подкачка по требованию — вы я определенно не получу физическую память для большей части возвращенного блока виртуальной памяти)

В старом DOS (не в 32-битном расширенном) вы даже не могли выделить более одной страницы за раз. Таким образом, ваша физическая память была больше, чем вы могли выделить (за один раз) на практике. Так что да, аппаратные ограничения могут «просачиваться»

Pepijn Kramer 30.07.2024 11:22

Ну, технически вы могли бы. Могла быть реализация, которая бы использовала 32-битный size_t и огромные указатели по умолчанию, а также fmemcpy для memcpy, fmalloc для malloc и т. д. Я думаю, что у watcom была огромная модель памяти? Просто обычно это делалось не из соображений производительности. Проблемы с аппаратной реализацией возникают не только в конкретных реализациях C++, но даже формируют сам стандарт (все ограничения на указатели связаны с тем, что они, возможно, сегментированы, или, например, когда подписанное переполнение стало законным и почему оно было незаконным раньше?)

Andrey Turkin 30.07.2024 12:50

Да, я помню модели памяти большего размера... даже ошибки в них (например, в одном компиляторе смещение все еще составляло 16 бит). И, конечно же, аппаратное обеспечение во многом налагает стандарты C++, большая часть UB тоже связана с этим. И watcom на x386 позволял переключиться в 32-битный режим... но с обработчиками прерываний было сложно... Хаха, те «добрые» старые времена ;) (где вы, по крайней мере, могли еще рассуждать о том, как на самом деле работает память/ЦП)

Pepijn Kramer 30.07.2024 12:57

Терминологическое примечание: MMU -> Блок управления памятью.

user4581301 30.07.2024 20:07

Другие вопросы по теме