2012-01-14 7 views
0
struct A { int i; }; 
... 
A *p = (A*) (8); // or A *p = 0; 
p->i = 5; // Undefined Behavior according C/C++ standard 

Однако практически большая часть системы врежется (ошибка сегментации) для такого кода.Указатель проверки косвенности для недействительного доступа к памяти и ошибки сегментации

Означает ли это, что все такие Архитектуры/Системы имеют скрытую проверку на отсутствие указателя (т. Е. p->), чтобы проверить, не имеет ли доступ к неправильной ячейке памяти?

Если да, то это означает, что даже в совершенно рабочий код мы расплачиваемся за это дополнительной проверки, правильно?

ответ

1

Нет, не совсем верно. Те же самые проверки абсолютно необходимы для правильного доступа к памяти по двум причинам:

1) В противном случае, как система узнает, к какой физической памяти вы обращались, и была ли эта страница уже резидентной?

2) В противном случае, как операционная система узнает, какие страницы физической памяти выходят на страницу, если физическая память стала жесткой?

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

1

Ошибка сегментации - это попытка получить доступ к памяти, к которой физически не может обращаться ЦП. Это происходит, когда аппаратное обеспечение уведомляет операционную систему о нарушении доступа к памяти. Поэтому я думаю, что нет никакой дополнительной проверки как таковой. Если попытка получить доступ к ячейке памяти не удалась, аппаратное обеспечение уведомляет ОС, которое затем отправляет сигнал процессу, вызвавшему исключение. По умолчанию процесс получает сигнал сбрасывает ядро ​​и завершается.

2

Обычно нет лишних скрытых проверок, это просто эффект использования виртуальной памяти.

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

2

Да, вы платите за эту дополнительную проверку. Это касается не только указателя, но и любого доступа к памяти (кроме, скажем, DMA). Однако стоимость проверки очень мала.

  • Пока ваш процесс запущен, таблица страниц не меняется очень часто. Части таблицы страниц будут кэшироваться в буфере трансляции трансляции, при этом доступ к страницам с записями в буфере не требует дополнительного штрафа.

  • Если ваш процесс обращается к странице без записи TLB, тогда CPU должен сделать дополнительный доступ к памяти для извлечения записи таблицы страниц для этой страницы. Затем он будет кэшироваться.

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

  • Над размером кеша L1 производительность снижается из-за латентности кэша L2.
  • Над размером кэша L2 производительность снизится до задержки в оперативной памяти.
  • Над размером памяти, адресуемой TLB, производительность снижается из-за пропусков TLB. (Это может произойти до или после того, как вы закончите свободное пространство L2, в зависимости от ряда факторов.)
  • Выше размера доступной оперативной памяти производительность снижается из-за обмена.
  • Над размером доступного пространства подкачки и оперативной памяти приложение будет прекращено ОС.

Если ваша операционная система разрешает «большие страницы», TLB может действительно покрыть очень большое адресное пространство. Возможно, вы можете саботировать ОС, выделив 4 тыс. Кусков от mmap, и в этом случае пропуски TLB могут ощущаться только с несколькими мегабайтами рабочего набора в зависимости от вашего процессора.

Однако: Небольшое падение производительности должно быть сопоставимо с преимуществами виртуальной памяти, которых слишком много, чтобы перечислять их здесь.

+0

Кажется странным, что ваш ответ явно «нет», но вы начинаете с «да». Вы не платите за дополнительную проверку действительности, она необходима для реализации виртуальной памяти. –

+0

@DavidSchwartz: Я считаю, что проверка прав на страницы является частью виртуальной памяти, поэтому да, проверка имеет стоимость, потому что виртуальная память имеет стоимость. Вам не обязательно соглашаться с этим, но вам не нужно спорить о семантике. –

+0

Он спросил, оплачивает ли рабочий код стоимость проверки на * дополнительную *, которая вызывает неправильный код. Это не. Дополнительная проверка действительности не требует затрат, потому что нет дополнительной проверки действительности. Проверка действительности не выполняется как дополнительная проверка, а часть проверок, необходимых для работы действительного кода. Это не просто семантическая проблема, кто-то, кто не читает ваш ответ близко и критически, может обернуться впечатлением, которое противоположно истине. –

1

Прежде всего, вам необходимо прочитать и понять это: http://en.wikipedia.org/wiki/Virtual_memory#Page_tables

Так что обычно случается, когда процесс пытается разыменованиями недействительной виртуальной ячейки памяти, операционная система перехватывает исключение ошибки страницы, поднятое MMU (см. ссылку выше) для недопустимого виртуального адреса (0x0, 0x8, что угодно). Затем ОС просматривает адрес в своей таблице страниц, не находит его и выдает сигнал SIGSEGV (или аналогичный) процессу, который приводит к сбою процесса.

Разница между допустимым и недействительным адресом заключается в том, выделила ли ОС страницу для этого диапазона адресов. Большинство ОС предназначены для того, чтобы никогда не выделять первую страницу (начальную с 0x0), так что разрывы NULL всегда будут сбой.

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