Неиспользуемая память в адресном пространстве защищена - PullRequest
5 голосов
/ 16 сентября 2011

Защищена ли неиспользуемая память в адресном пространстве процесса только наличием разрешения на чтение, так что запись в местоположение, указанное, например, указателем, унифицированным указателем, всегда приводит к тому, что ОС фиксирует ошибку страницы?Или это не тот случай, и каждой ячейке памяти, кроме кода (какой доступ предоставляется только для чтения), предоставляется доступ на запись?

Я спрашиваю об этом, потому что мой друг показывал мне свой код, где онне инициализировал указатель и записывал в память, указанную им, но его программа не работала с компилятором mingw gcc для окон, а всегда с Visual C ++, в Mac или Linux.

Я думаю, что ОС не защищает память для неиспользуемых областей, и происходит сбой, потому что в коде, сгенерированном mingw, значение случайного указателя указывало на некоторую используемую область, такую ​​как стек, кучаили код, в то время как в других случаях это указывало на некоторую свободную область.Но если ОС действительно не защищает неиспользуемые области, не будут ли такие ошибки, такие как неинициализированные указатели, трудными для отладки?

Полагаю, именно поэтому рекомендуется всегда назначать NULL указателю после вызова delete или free, чтобы при обращении к нему что-то действительно вызывало видимый сбой.

Ответы [ 5 ]

3 голосов
/ 16 сентября 2011

В типичной текущей серверной / настольной ОС (а также в нескольких небольших системах, таких как сотовые телефоны) у вас есть виртуальная память. Это означает, что ОС создает таблицу, которая преобразует виртуальный адрес, который использует ваш код, в физический адрес, который указывает фактическую адресуемую память. Такое сопоставление обычно выполняется в «страницах» - например, 4 КБ порции памяти за раз.

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

3 голосов
/ 16 сентября 2011

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

2 голосов
/ 17 сентября 2011

Защита памяти не обеспечивается c / c ++. Вы можете обнаружить, что указатель просто содержит указатель на действительную память, например, предыдущая функция имеет переменную ptr в стеке, а другая функция, вызываемая позже, просто использует то же пространство стека для указателя.

Следующий код выведет «Hello», если он скомпилирован и запущен с gcc: #include

char buffer[10];

void function1(void) {
    char * ptr = buffer;
    sprintf(buffer, "Hello");
    return;
}

void function2(void) {
    char * ptr2;
    printf("%s\n", ptr2);
}

int main(int argc, char * argv[]) {
    function1();
    function2();
}

Для отладочных сборок некоторые компиляторы (я знаю, что Visual Studio использовал для этого) будут тайно инициализировать все переменные, такие как ptr2, в неверное значение для обнаружения ошибок такого типа.

Обычно с помощью C вы обнаруживаете, что операционная система, убивающая вашу программу, злоупотребляет памятью.

2 голосов
/ 16 сентября 2011

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

1 голос
/ 16 сентября 2011

Проще говоря, я предполагаю, что ответ «Нет, неиспользуемая память в адресе не защищена». C не достаточно сложен, чтобы справиться с такими случаями.

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