@prometian

Почему нет ругани на модификацию стороннего куска памяти?

Добрый день!
Следующий код объявляет и инициализирует массив, а так же указатель на массив.
Изначально указатель стоит на начале массива и увеличивается пока не дойдет до адреса последнего элемента.
Почему, если мы объявили 500 элементов, а первый начинается с индекса 0, программа спокойно дает нам выйти за пределы массива и модифицировать память?
Правильно ли я думаю что в случае с указателями никакой проверки не проводится вообще и ошибка может возникнуть, а может и отсутствовать, а правильным должно быть условие while (pTmp != &tmp[499]) ?
Каким образом можно проверить что участок памяти доступен для записи не вызывая ошибку или try catch единственный способ?

int32_t tmp[500];
int32_t * pTmp = tmp;

{
for (int i = 0; i < 500; i++)
{
tmp[i] = i;
}
}

while (pTmp != &tmp[500])
{
*pTmp = *pTmp * 10;

pTmp++;
}

_getch();
return 0;
  • Вопрос задан
  • 2218 просмотров
Решения вопроса 1
Запись по невалидному указателю - это UB (undefined behavior), т.е. по стандарту произойти может что угодно. На деле просто пишется туда, куда сказали, что может вызвать как структурное исключение (SEH, не путать с обычными исключениями C++) на Windows или SIGSEGV на Unix'ах, а может и не вызвать, если по данному указателю запись возможна. Т.о. try-catch не решение по двум причинам:
1. Исключение даже если и будет, то не C++ (хотя, к примеру, студия позволяет SEH'и ловить "обычным" catch)
2. Исключение не гарантировано

Проверять, что память доступна для записи в общем случае бессмысленно, так как она вполне может быть доступна, но по адресу лежит не массив, а какие-то другие данные, которые тем не менее можно перезаписать, поломав программу. Решение заключается в том, чтобы не писать туда, куда не нужно, т.е. сводить к минимуму манипулирование голыми указателями без должной осторожности и понимания.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
GavriKos
@GavriKos
Проверка происходит грубо говоря на уровне ОС. Например, XP и win7 в случае записи за предел массива реагируют по разному - семерка чаще всего крешит приложение, семерка - отработает.

Вообще проверка а указывает ли указатель куда надо всегда на совести программиста. Причем может вполне валидным быть наращивание указателя за пределы первого массива - например если вы гарантируете что за первым массивом сразу идет второй массив.
Ответ написан
Комментировать
AxisPod
@AxisPod
А почему должна быть проверка? Может стоит почитать книги для начала. C/C++ это не те языки, где можно изучать методом научного тыка. В C/C++ нет контроля выхода за границы, если хотите, берите Java, C# и т.д.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы