Какие адресные пространства памяти существуют?

Какие формы адресного пространства памяти были использованы?

Сегодня широко распространено большое плоское виртуальное адресное пространство. Исторически использовались более сложные адресные пространства, такие как пара базового адреса и смещения, пара номера сегмента и смещения, адрес слова плюс некоторый индекс для байта или другого подобъекта и т. Д. ,

Время от времени в различных ответах и ​​комментариях утверждается, что указатели C / C ++ являются по существу целыми числами. Это неверная модель для C / C ++, поскольку разнообразие адресных пространств, несомненно, является причиной некоторых правил C относительно операций с указателями. Например, отсутствие определения арифметики указателей вне массива упрощает поддержку указателей в базовой и смещенной модели. Ограничения на преобразование указателей упрощают поддержку моделей «адрес плюс дополнительные данные».

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

Полезная информация может включать в себя:

  • Примеры компьютерных архитектур с различными адресными пространствами и описания этих пространств.
  • Примеры различных адресных пространств, все еще используемых в машинах, которые в настоящее время производятся.
  • Ссылки на документацию или пояснения, особенно URL.
  • Разработка того, как адресные пространства мотивируют правила указателя C / C ++.

Это широкий вопрос, поэтому я открыт для предложений по управлению им. Я был бы рад видеть совместное редактирование одного и того же всеобъемлющего ответа. Тем не менее, это может не дать репутацию заслуженным. Я предлагаю внести несколько полезных вкладов.

20

Решение

Почти все, что вы можете себе представить, возможно, было использовано.
первое основное разделение между байтовой адресацией (все современные
архитектуры) и адресация слов (до IBM 360 / PDP-11, но
Я думаю, что современные мейнфреймы Unisys все еще адресуются). В
адресация слов, char* а также void* часто будет больше, чем
int*; даже если бы они не были больше, «селектор байтов» был бы в старших битах, которые должны были быть 0, или
будет игнорироваться для всего, кроме байтов. (На PDP-10,
например, если p был char*, (int)p < (int)(p+1) было бы
часто быть ложным, даже если int а также char* было то же самое
размер.)

Среди машин с байтовой адресацией основные варианты сегментированы
и несегментированные архитектуры. Оба по-прежнему широко распространены
сегодня, хотя в случае с Intel 32bit (сегментированный
архитектура с 48-битными адресами), некоторые из
используемые ОС (Windows и Linux) искусственно ограничивают пользователя
обрабатывает в один сегмент, имитируя плоскую адресацию.

Хотя у меня нет недавнего опыта, я бы ожидал даже больше
Разнообразие встроенных процессоров. В частности, в прошлом это
было часто для встроенных процессоров использовать Гарвард
архитектура, где код и данные были в независимом адресе
пробелы (так что указатель на функцию и указатель данных, приведенный к
достаточно большой интегральный тип, мог бы сравниться равным).

16

Другие решения

Я бы сказал, что вы задаете не тот вопрос, кроме исторического любопытства.

Даже если ваша система использует плоское адресное пространство — даже если каждая система с настоящего момента и до конца времени использует плоское адресное пространство — вы все равно не можете рассматривать указатели как целые числа.

Стандарты C и C ++ оставляют все виды арифметики указателей «неопределенными». Это может повлиять на вас прямо сейчас, в любой системе, потому что компиляторы предполагают, что вы избегаете неопределенного поведения и соответственно оптимизируете.

Для конкретного примера, три месяца назад в Valgrind появилась очень интересная ошибка:

http://comments.gmane.org/gmane.comp.debugging.valgrind.devel/19698

(Поиск «неопределенное поведение».)

По сути, Вальгринд использовал указатели «меньше» и «больше», чтобы попытаться определить, находится ли автоматическая переменная в определенном диапазоне. Поскольку сравнения между указателями в разных агрегатах «неопределены», Clang просто оптимизирован все из сравнений, чтобы вернуть константу true (или false; я забыл).

Эта ошибка сама породила интересный вопрос StackOverflow.

Таким образом, хотя первоначальные арифметические определения указателей могли быть ориентированы на реальные машины, и это само по себе может быть интересно, на самом деле это не имеет отношения к программированию сегодня. Сегодня важно то, что вы просто не можете предположить, что указатели ведут себя как целые числа, точка, независимо от системы, которую вы используете. «Неопределенное поведение» не означает «что-то смешное происходит»; это означает, что компилятор может предположить, что вы этим не занимаетесь. Когда вы это делаете, вы вводите противоречие в рассуждения компилятора; и из противоречия вытекает все что угодно … Это зависит только от того, насколько умен ваш компилятор.

И они становятся умнее все время.

5