LINUX.ORG.RU

История изменений

Исправление Vic, (текущая версия) :

Почему компилятор пропускает такое ?

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

Ведь понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

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

С точки зрения процессора — «ошибки выхода за границы» не существует, т.к. у процессора есть адресное пространство, процессор может читать и писать в любое место своего адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исправление Vic, :

Почему компилятор пропускает такое ?

А как компилятор (любой) может этого не допускать? Он чисто физически такого сделать не может.

Ведь понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

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

С точки зрения процессора — «ошибки выхода за границы» не существует, т.к. у процессора есть адресное пространство, процессор может читать и писать в любое место своего адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исправление Vic, :

Почему компилятор пропускает такое ?

А как компилятор (любой) может этого не допускать? Он чисто физически такого сделать не может.

Ведь понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

А с точки зрения процессора — «ошибки выхода за границы» не существует, т.к. у процессора есть адресное пространство, процессор может читать и писать в любое место своего адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исправление Vic, :

Почему компилятор пропускает такое ?

А как компилятор (любой) может этого не допускать? Он чисто физически такого сделать не может.

Ведь понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

У процессора есть адресное пространство, процессор может читать и писать в любое место адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исправление Vic, :

Почему компилятор пропускает такое ?

А как компилятор может этого не допускать?

Ведь понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

У процессора есть адресное пространство, процессор может читать и писать в любое место адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исправление Vic, :

Понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

У процессора есть адресное пространство, процессор может читать и писать в любое место адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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

Исходная версия Vic, :

Понятие «выход за границу памяти» — это чисто человеческое, субъективное понятие, придуманное для контроля работы алгоритмов конкретной программы, что бы программа не заставляла процессор читать/писать в области адресов, которые ей не положены по логике ее работы.

У процессора есть адресное пространство, процессор может читать и писать в любое место адресного пространства. Программа лишь управляет процессором, что куда и откуда читать/писать.

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

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

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

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

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

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

  • или загрузить только то, что поместиться в массив
  • или отказаться от загрузки
  • или оповестить пользователя
  • или еще что-то, что зависит только от логики работы программы

В некоторых языках стараются придумывать всякие встроенные защитные механизмы, но они замедляют работу (т.к. добавляется множество проверок) и все-равно принципиально не защищают от всех ошибок. Поэтому, единого решения про ошибки — нет, споры идут до сих пор. Например, вот так пытаются делать в RUST, заставляя программиста обрабатывать потенциальные ошибки: https://habr.com/ru/companies/otus/articles/579538/

Например, в примере выше, загружая мегабайтный файл в переменную массив на килобайт и выходя за пределы переменной массива, программа может не выйти за разрешенные ОС пределы, но может испортить все остальные свои переменные и начнет «глючить» — т.е. продолжать работать, но как-то странно и непонятно.

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