Почему я не могу напечатать значение адреса 0? - PullRequest
1 голос
/ 02 февраля 2012

Я играю с указателями, чтобы понять их, поэтому я хотел бы знать, почему я не могу, например, напечатать значение адреса 0 (ноль) и другие.

#include <stdio.h>
int main()
{
    int *i = 0;
    int *e = (int*)0x100;

    while (i <= e)
    {
        printf("%d\n", *i);
        i++;
    }

    return 0;
}

В этом примере происходит сбой.

Ответы [ 6 ]

2 голосов
/ 02 февраля 2012

нарушение прав доступа ...

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

Проще говоря, нарушение доступа происходит каждый раз, когда к области памяти обращаются, к которой у программы нет доступа.

http://blogs.technet.com/b/askperf/archive/2008/06/03/access-violation-how-dare-you.aspx

2 голосов
/ 02 февраля 2012

Вы можете разыменовать только действительные указатели.Это указатели, возвращаемые, например, из malloc(), или указатели, сгенерированные путем взятия адреса чего-либо.Разыменование недопустимого указателя является неопределенным поведением.

В вашем случае ваша операционная система, скорее всего, не позволяет вам читать память, которая не сопоставлена ​​с вашим процессом, именно поэтому она убивает процесс при попытке.

1 голос
/ 02 февраля 2012

Из стандарта C, пункт 6.5.3.2/4

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

Примером недопустимого значения является нулевой указатель. То, что вы делаете, может работать, а может и не работать. Я знаю, что на HP-UX 11.31 с gcc 4.3.1 он будет работать и не падать. в твоем случае он падает. Как видите, стандарт не навязывает какое-либо конкретное поведение в этой ситуации.

1 голос
/ 02 февраля 2012

0 является константой нулевого указателя

(C99, 6.3.2.3p3): «Целочисленное константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя.»

Разыменование нулевого указателя: неопределенное поведение .

(C99, 6.5.3.2.p4) "Если указателю было присвоено недопустимое значение, поведение унарного оператора * не определено.87)"

и

87): «Среди недопустимых значений для разыменования указателя с помощью унарного оператора * есть нулевой указатель, адрес, неправильно выровненный для типа объекта, на который указывает объект, и адрес объекта после окончания его времени жизни. "

0 голосов
/ 02 февраля 2012

Не все адреса в адресном пространстве отображаются в фактическую ячейку памяти в модуле физической памяти.Когда вы пытаетесь прочитать значение по адресу NULL (т. Е. Ячейку по адресу 0), которое не сопоставлено ни с чем, ваша система обнаруживает его и убивает ваш процесс с помощью сигнала segmentation falt или чего-то подобного.

0 голосов
/ 02 февраля 2012

Вы, вероятно, пытаетесь получить доступ к памяти, к которой ваша программа не имеет доступа, и "крах" - это просто система, предотвращающая его уничтожение вирусом (вами :)).

Вот небольшой код Linuxскомпилировано с gcc:

#include <stdio.h>

int b;

int main() {
    char *ptr = (char*)&b;
    ptr -= 2368;
    int i;

    for( i = 0; i < 3984; i++){
        printf( "%d: %c\n", i, ptr[i]);
    }

    printf( "\n");

    return 0;
}

Если вы попытаетесь получить доступ к -2369 байтам, вы получите ошибку сегментации (нарушение доступа).Если вы попытаетесь получить доступ к более чем 3984-му байту (3983-й, включая «нулевой байт»), вы получите ту же ошибку (вероятно, это размер страницы, который можно использовать для приложений).

char *ptr = (char*)&main;
ptr -= 999;
int i;

for( i = 0; i < 3763; i++){
    printf( "%c", ptr[i]);
}

В моей системе есть адрес b: 0x600970

И адрес основного: 0x4004e4

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...