#c #memory #pointers
#c #память #указатели
Вопрос:
Предположим, я делаю следующее
int *p = 1;
printf("%d", *p);
Я получаю ошибку сегментации. Теперь, насколько я понимаю, эта ячейка памяти 1 находится в адресном пространстве моей программы. Почему должна быть проблема при чтении этой ячейки памяти?
Ответ №1:
Ваш указатель не указывает ни на что действительное. Все, что вы делаете, это присваиваете значение 1
указателю на int, но 1
это недопустимая ячейка памяти.
Единственный допустимый способ получить значение указателя - это либо взять адрес переменной, либо вызвать функцию распределения:
int a;
int * p1 = amp;a; // OK
int * p2 = malloc(sizeof(int)); // also OK
*p1 = 2;
*p2 = 3;
Что касается "почему должна быть проблема": что касается языка, если вы разыменовываете недопустимый указатель, у вас неопределенное поведение, поэтому может случиться все, что угодно - это действительно единственный разумный способ указать язык, если вы не хотите вводить какие-либо произвольные ограничения, и Cвсе дело в простоте реализации.
Практически, современные операционные системы обычно имеют умный менеджер виртуальной памяти, который должен запрашивать память, когда и по мере необходимости, и если память по адресу 1
еще не зафиксирована на странице, вы действительно получите сообщение об ошибке от ОС. Если вы попытаетесь ввести значение указателя рядом с некоторым фактическим адресом, вы можете не получить ошибку (возможно, пока не перейдете границу страницы).
Ответ №2:
Правильный ответ на этот вопрос действительно будет зависеть от ряда факторов. Однако вполне вероятно, что адрес 0x00000001 (страница 0) не сопоставлен и / или не защищен от чтения.
Обычно адреса в диапазоне страниц 0 запрещены для пользовательского приложения по той или иной причине. Даже в пространстве ядра (в зависимости от процессора) адреса на странице 0 часто защищены и требуют, чтобы страница была отображена и доступ к ней был разрешен.
РЕДАКТИРОВАТЬ: Другая возможная причина заключается в том, что это может быть нарушение сегментации, поскольку доступ к целому числу не выровнен.
Комментарии:
1. 1 за упоминание о том, что сопоставление страницы 0 запрещено даже в защищенных операционных системах (это может привести к эксплойтам против ядра).
Ответ №3:
Ваша операционная система не позволит вам получить доступ к ячейкам памяти, которые не принадлежат вашей программе. Однако это будет работать в режиме ядра...
Комментарии:
1. Я думал, что у каждого процесса есть свое собственное виртуальное адресное пространство. Итак, начиная с 0x0, все пространство принадлежит моему процессу, и я должен иметь к нему доступ?
2. @AnkurVj: все виртуальное пространство принадлежит вам, но вам все равно нужно сначала выделить его, чтобы оно было допустимым местоположением.
3. Предположим, я объявляю целое число и печатаю его адрес. Является ли это местоположение реальной физической ячейкой памяти?
4. @AnkurVj: Это логический адрес, который был выделен системой.
Ответ №4:
Нет, адрес 1 отсутствует в адресном пространстве вашей программы. Вы пытаетесь получить доступ к сегменту, который вам не принадлежит, и получаете ошибку сегментации.
Ответ №5:
Вы пытаетесь напечатать 1, а не ячейку памяти. 1 не является допустимой ячейкой памяти. Чтобы распечатать фактическую ячейку памяти, выполните:
printf("%p", p);
Обратите внимание на %p, как указал icktoofay.
Комментарии:
1. Я считаю, что правильная спецификация форматирования для указателя %p
- нет %d
.
2. Нет. Я не пытаюсь распечатать ячейку памяти. Я действительно пытаюсь распечатать то, что хранится в этой ячейке памяти
3.Я думаю, что он на самом деле пытается вывести int
адрес at 1.