Индекс находится за границами массива

Вопрос: Почему мы можем писать вне границ в C?

Недавно я закончил чтение о виртуальной памяти, и у меня возник вопрос о том, как malloc работает в виртуальном адресном пространстве и физической памяти.

Например (код, скопированный с другого сообщения SO)

Почему это разрешено? Или, например, почему этот адрес в p даже доступен для записи?

Вот моя догадка.

Когда вызывается malloc, возможно, ОС решает дать процессу целую страницу. Я просто предполагаю, что каждая страница стоит 4 Кбайт пространства. Это целая вещь, обозначенная как доступная для записи? Вот почему вы можете зайти на страницу размером 500 * sizeof (int) (предполагая 32-битную систему, где int — 4 байта).

Я вижу, что когда я пытаюсь редактировать с большим значением …

Seg.

Если это так, значит, это означает, что есть страницы, которые посвящены вашим фрагментам кода / инструкций / текста и помечены как незарегистрированные, полностью отделенные от ваших страниц, на которых находятся ваш стек / переменные (где вещи меняются) и помечены как записываемые ? Конечно, этот процесс предполагает, что они находятся рядом с каждым заказом в адресном пространстве 4gb на 32-битной системе.

6

2018-03-19 02:34

источник

Ответы:

Рассмотрим следующий код для Linux:

Он печатает карту памяти процесса и адреса некоторых типов памяти.

Или, например, почему этот адрес в p даже доступен для записи?

Heap от 0824d000-0826f000 и & p случайно 0x824ea70, поэтому память может записываться и читаться, но в этой области памяти могут содержаться реальные данные, которые будут изменены! В случае с образцовой программой, скорее всего, она не используется, поэтому запись в эту память не вредна для работы процесса.

& p случайным образом равен 0x1410a4a0, который не находится на странице, которую ядро ​​отображает на процесс, и поэтому является неприемлемым и нечитаемым, следовательно, сбой seg.

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

Если это так, значит, это означает, что есть страницы, которые посвящены вашим фрагментам кода / инструкций / текста и помечены как незарегистрированные, полностью отделенные от ваших страниц, на которых находятся ваш стек / переменные (где вещи меняются) и помечены как записываемые ?

Да, см. Вывод карты памяти процесса выше. означает читаемый и исполняемый файл,  означает читаемость и запись.

5

2018-03-19 18:47

«Почему это разрешено?» (писать за пределами границ)

C не требует дополнительных инструкций ЦП, которые обычно необходимы для предотвращения этого доступа за пределами диапазона.

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

12

2018-03-19 02:43

Почему это разрешено?

Одной из основных целей дизайна языков C (и C ++) должно быть максимально эффективное время выполнения.

Дополнительные возможности Jira

Дизайнеры C (или C ++) могли бы принять решение о включении правила в спецификацию языка, в котором говорится, что «запись вне границ массива должна приводить к тому, что X» (где X — это определенное поведение, такое как сбой или брошенное исключение) … но если бы они это сделали, каждый компилятор C был бы обязательный  для создания кода проверки границ для каждого доступа к массиву, который выполняет программа C. В зависимости от целевого оборудования и умения компилятора, применение такого правила может легко сделать каждую программу C (или C ++) в 5-10 раз медленнее, чем она может быть в данный момент.

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

Реальные реализации реализаций теперь свободны делать все, что они хотят — например, в ОС с защитой памяти вы, скорее всего, увидите поведение на основе страниц, как вы описали, или во встроенном устройстве (или на более старых ОС, таких как MacOS 9, MS -DOS или AmigaDOS) компьютер может просто счастливо позволить вам писать в любом месте в памяти, потому что иначе сделать компьютер слишком медленным.

Будучи языком низкого уровня (по современным стандартам), C (C ++) ожидает, что программист будет следовать правилам и будет только механически применять эти правила, если / когда он сможет это сделать, не навлекая на себя служебные расходы.

4

2018-03-19 02:42

Неопределенное поведение ,

Это и есть. Вы Можно  старайтесь писать за пределами, но это не гарантированный  работать. Это может сработать, возможно, нет. То, что происходит, совершенно не определено.

Почему это разрешено?

Потому что это позволяют стандарты C и C ++. Языки предназначены для быстро , Для проверки доступа за пределы доступа потребуется работа во время выполнения, что замедлит работу программы.

почему этот адрес в p даже доступен для записи?

Это только что произошло  быть. Неопределенное поведение.

Я вижу, что когда я пытаюсь редактировать с большим значением …

Видеть? Опять же, это только что произошло  к segfault.

Когда вызывается malloc, возможно, ОС решает дать процессу целую страницу.

Возможно, но стандарты C и C ++ не требуют такого поведения. Они требуют только, чтобы ОС делала по меньшей мере запрошенный объем памяти, доступный для использования программой. (Если есть доступная память.)

2

2018-03-19 02:36

Просто в C понятие массива довольно элементарно.

Назначение p находится в C так же, как:

и все, что делает компилятор, это:

Во многих архитектурах это реализуется в одной или двух инструкциях.

Обратите внимание, что компилятор не только не знает, что значение 500 не находится в массиве, но и не знает размер массива для начала!

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

Перефразируй. В Pascal компилятор не позволит вам стрелять ногой. В C ++ компилятор предоставляет способы сделать его более трудным для стрельбы по вашей ноге, в то время как в C компилятор даже не знает, что у вас есть нога.

1

2018-03-19 02:42

Это неопределенное поведение …

  • если вы пытаетесь получить доступ к внешним границам, все может случиться, в том числе SIGEGV или коррупция в другом месте стека, из-за чего ваша программа производит неправильные результаты, зависает, падает позже и т. д.

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

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

Почему это разрешилось?

Для этого есть два аспекта:

  • проверка индексов на каждом доступе раздувается (добавляет дополнительные инструкции машинного кода) и замедляет выполнение программы, и, как правило, программист может выполнять некоторую минимальную проверку индексов (например, проверять один раз при вводе функции, а затем использовать индекс, однако, много раз ) или генерировать индексы таким образом, чтобы гарантировать их достоверность (например, цикл от 0 до размера массива)

  • очень точно управляя памятью, так что доступ с ограниченным доступом сообщается с некоторым сбоем процессора, сильно зависит от аппаратного обеспечения и вообще возможен только на границах страниц (например, гранулярность в диапазоне от 1 до 4 тыс.), а также при использовании дополнительных инструкции (будь то в некоторых  функции или в некоторых -wrapping code) и время для оркестровки.

1

2018-03-19 02:41

Популярные вопросы:

Perl — буквенные буквенные обозначенияlibpython2.7.so.1.0: невозможно открыть файл общих объектов: нет такого файла или каталогаКак написать литерал в C ++ 11? Java Быстрая проверка сетевого подключенияКакое регулярное выражение можно использовать для соответствия любому действительному IP-адресу, представленному в десятичной форме?настройка теряет позицию каретки в элементе при нажатии клавиши TABЯ хочу создать чат с помощью Rails, следует ли использовать juggernaut 2 или cramp?

О проверках выхода индексов за границы массивов

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

Помощь в паскале

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

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

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

На самом деле экспериментальное изучение программ доказывает, что и тот и другой эффект в подавляющем большинстве случаев ничтожен (при условии тщательного дизайна языка и компилятора, как это имеет место для Оберона/Компонентного Паскаля).
Жертвовать же надежностью всех программ ради ускорения пусть даже на десяток процентов в редком случае — безответственно (гораздо чаще имеет место замедление на уровне 1%, если его вообще удается достоверно измерить).
Если же такая редкая программа предназначена для частого использования, то и оптимизировать ее нужно особыми методами, например, переписав соответствующий фрагмент непосредственно в машинных кодах (цикл, в котором проверка индексов заметно сказывается на производительности, вряд ли будет сложным, так что написать несколько команд в машинных кодах труда не составит для специалистов, которые обычно занимаются такими программами; о том, как включать фрагменты в машинных кодах непосредственно в программу на Компонентном Паскале, см. в документации Блэкбокса Platform-Specific Issues, разделCode procedures).

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

Посмотрим с этой точки зрения на вариант ошибки такого рода из числа наихудших — а именно, на ситуацию, когда данные, записываемые в массив, поступают из Интернета. В таком случае, если программа не проверяет выход за границу буфера — массива, предназначенного для записи приходящей из Интернета информации, — можно заставить программу записать в какую-то область памяти исполняемый код и даже передать ему управление, тем самым перехватив управление компьютером. Именно в этом состоит излюбленный хакерами способ проникать в компьютеры, подключенные к Интернету — атака посредством переполнения буфера (buffer overflow).

Сообщениями о таких атаках пестрят новостные ленты компьютерного мира. Например, вспомним одну поучительную историю. В августе 2001 г. вице-президент Майкрософт Джим Олчин (Jim Allchin) объявил во время доклада на открытии конференции Intel Developers Forum в Сан Хосе, что в новой операционной системе Windows XP все возможные проблемы из разряда переполнение буфера были устранены посредством специального анализа исходных текстов на предмет безопасности (security audit). Но в декабре того же года была найдена «дыра»в одной из программ в составе Windows XP (в программах поддержки стандарта подключения внешних устройств Universal Plug and Play) — причем дыра оказалась именно из категории переполнение буфера.

  • Вопрос: Что мешает Майкрософт компилировать Windows XP с включенной опцией контроля выхода за границы массивов?
    Ответ: Неадкватность языков и компиляторов, использованных в написании операционной системы (C и C++).
  • Вопрос: Почему аудит исходных текстов, о котором объявил Джим Олчин, не обнаружил этой проблемы?
    Ответ: Потому что вовсе не равна нулю вероятность ошибиться живым людям, выполнявшим аудит 50 миллионов строк программ на нечитабельном языке типа C.

  • Вопрос: Почему столь важный продукт, как операционная система, используемая на сотне миллионов компьютеров во всем мире, строится на столь гнилом фундаменте, как язык программирования, для которого нельзя написать компилятор, генерирующий эффективный и безопасный код, с тем чтобы переложить тривиальный механический труд по нудной проверке индексов массивов с человека, которому свойственно ошибаться при выполнении механических процедур, на компьютер, который именно для таких процедур и придуман?
    Ответ: Потому что подавляющее большинство программистов Майкрософт, начиная с Билла Гейтса, — как бы хорошо ни была организована их работа и какими бы талантливыми индивидуумами они ни были сами по себе — классические программисты-самоучки, втянутые в круговорот компьютерной революции большими деньгами и задумывающиеся о методологии программирования только под сильной угрозой со стороны конкурентов.

В начале 2002 г. Майкрософт на месяц приостановила нормальную работу, чтобы программистский персонал мог специально сосредоточиться на проблемах безопасности и надежности программ. Если оценить количество программистов Майкрософт в 20 тысяч человек при зарплате от $150тыс. в год и выше, то стоимость месячника повышения квалификации выйдет не меньше 250 миллионов долларов. Майкрософт в состоянии это себе позволить. Остальным, видимо, все же дешевле перейти на инструменты программирования, где проверки индексов массивов не отключаются. Впрочем, и сама компания Майкрософт в настоящее время переходит на платформу .NET, в которой главный язык программирования — т.наз. C# — смоделирован во многом, в том числе и в отношении безопасности программирования, по образцу Оберона.

Индекс находился вне границ массива. (Microsoft.SqlServer.smo)

Индекс находится за границами массива

Я
   137 При попытке оприходовать товар приходным ордером 8-ка выдает ошибку:

Ошибка при выполнении обработчика — ‘{ОбщийМодуль.УправлениеЗапасами(521)}: Индекс находится за границами массива’
по причине:
{ОбщийМодуль.УправлениеЗапасами(521)}: Индекс находится за границами массива
ЧТО ДЕЛАТЬ ?
 
     France

загнать индекс в границы массива.

   Rovan

Может релиз обновить.
(0) Какой № ?

   137

где индекс и как его загнать в границы

   137

релиз   1С:Предприятие 8.0 (8.0.11.3)

   Факер_S

(4) поэтому такие ошибки вываливаются

   Факер_S

пустых строк в ТабличныхЧастях нет?

   Rovan

(4) Покажи код модуля ОбщийМодуль.УправлениеЗапасами
строки с 505 по 535

   137

ЕСТЬ. Но все что может быть заполненно заполненно.

   Факер_S

(8) у меня на пустые строки наподобии ругается не выяснял в чем дело

   137 ЭТО СТРОКИ 505   535 ОБЩЕГО МОДУЛЯ УПРАВЛЕНИЕ ЗАПАСАМИ.

Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ " + Сред(СтрокиЗапроса, 2) + " | ИЗ | Документ." + ДокументОбъект.Метаданные().Имя + " КАК Док " + ТаблицыЗапроса + СтрокаЗапросаКурсыВалютыРеглУчета + ?(НуженКурсВалютыУпрУчета, СтрокаЗапросаКурсыВалютыУпрУчета,"") + ?(ЕстьУчетнаяПолитика, СтрокаРегистраУчетнойПолитики,"") + " | ГДЕ Док.Ссылка = &ДокументСсылка"; // Установим параметры запроса. Запрос.УстановитьПараметр("ДокументСсылка" , ДокументОбъект.Ссылка); Запрос.УстановитьПараметр("ДатаДокумента", ДокументОбъект.Дата); ТаблицаЗапроса = Запрос.Выполнить().Выгрузить(); Для каждого Колонка из ТаблицаЗапроса.Колонки Цикл Если ТаблицаЗапроса.Количество() = 0 Тогда СтруктураШапкиДокумента.Вставить(Колонка.Имя, Неопределено); Иначе СтруктураШапкиДокумента.Вставить(Колонка.Имя, ТаблицаЗапроса); КонецЕсли; КонецЦикла; Если СтруктураШапкиДокумента.Свойство("ВалютаВзаиморасчетов") Тогда СтруктураШапкиДокумента.Вставить("КурсДокумента", КурсДокумента(ДокументОбъект, ВалютаРегламентированногоУчета)); СтруктураШапкиДокумента.Вставить("КратностьДокумента", КратностьДокумента(ДокументОбъект, ВалютаРегламентированногоУчета)); КонецЕсли; Возврат СтруктураШапкиДокумента; КонецФункции// СформироватьЗапросПоДеревуПолей()

 
 

   France

ругаецца на ТаблицаЗапроса — проверь его..

Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа.
Фредерик Брукс-младший

ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.

Минимальный четный элемент и его индекс

Ветка сдана в архив. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.

Ошибка — индекс находится за пределами массива

Я
   DrakoH

Здравствуйте. Кто-нибудь встречался с ошибкой "Индекс находится за пределами массива"? У меня она возникла в БГУ 1.0.6.3 при формировании отчета "Оборотная ведомость по НФА". Слышал, что подоные ошибки и раньше возникали у людей, но о применяемых методах решения проблемы пока не задумывался (пока сам не дожил до нее)…
Кто знает, где копать?

 
 

   zladenuw

ну так переход в конфигуратор.

Как изменить ошибку: «Индекс находится вне границы массива»?

ставишь там точку остановки и смотришь на каком моменте падает.

   izekia

(0) (1) имел в видe установить остановку по ошибке

   zladenuw

(2) зачем такую подсказку дал

   izekia

(3) а ты зачем?

   CepeLLlka

Скорее всего это значит что номера строки массива которую вы хотите получить не существует..

К примеру у нас массив из 10 позиций..  а мы пищем — Получить массив, тогда он нам высдат что индекс находится за пределами массива

   izekia

(3) вот Сергей в правильном ключе взялся решать, видимо прочитал только заголовок темы)

   Agema

"Тестирование и исправление", где-то в базе ссылка на строку или документ, который удален.

   DrakoH

Спасибо. чейчас буду смотреть.

   izekia

(7) это-то причем?

   Ненавижу 1С

(5) даже массив выдаст ошибку

 
 

   izekia

(10) ну это он с запасом

   CepeLLlka

Я вот пытаюсь помочь людям.. а вы вот так ко мне..
Напиши я 10, а не ёё, незнающий человек сделал бы вот так — О_О
А так понятно.. а потом сам уже увидит что счётчик с 0 идёт.

   Ненавижу 1С

(12) зато беседа была бы интереснее ))

   DrakoH

CepeLLlka, спасибо. не обращайте внимания на этих коршунов)

   Ненавижу 1С

(14) да мы милые и пушистые ))

TurboConf 5 — расширение возможностей Конфигуратора 1С

ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.

Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.

Вопрос: Почему мы можем писать вне границ в C?

Недавно я закончил чтение о виртуальной памяти, и у меня возник вопрос о том, как malloc работает в виртуальном адресном пространстве и физической памяти.

Например (код, скопированный с другого сообщения SO)

Почему это разрешено? Или, например, почему этот адрес в p даже доступен для записи?

Вот моя догадка.

Когда вызывается malloc, возможно, ОС решает дать процессу целую страницу. Я просто предполагаю, что каждая страница стоит 4 Кбайт пространства. Это целая вещь, обозначенная как доступная для записи? Вот почему вы можете зайти на страницу размером 500 * sizeof (int) (предполагая 32-битную систему, где int — 4 байта).

Я вижу, что когда я пытаюсь редактировать с большим значением …

Seg.

Если это так, значит, это означает, что есть страницы, которые посвящены вашим фрагментам кода / инструкций / текста и помечены как незарегистрированные, полностью отделенные от ваших страниц, на которых находятся ваш стек / переменные (где вещи меняются) и помечены как записываемые ? Конечно, этот процесс предполагает, что они находятся рядом с каждым заказом в адресном пространстве 4gb на 32-битной системе.

6

2018-03-19 02:34

источник

Ответы:

Рассмотрим следующий код для Linux:

Он печатает карту памяти процесса и адреса некоторых типов памяти.

Или, например, почему этот адрес в p даже доступен для записи?

Heap от 0824d000-0826f000 и & p случайно 0x824ea70, поэтому память может записываться и читаться, но в этой области памяти могут содержаться реальные данные, которые будут изменены! В случае с образцовой программой, скорее всего, она не используется, поэтому запись в эту память не вредна для работы процесса.

& p случайным образом равен 0x1410a4a0, который не находится на странице, которую ядро ​​отображает на процесс, и поэтому является неприемлемым и нечитаемым, следовательно, сбой seg.

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

Если это так, значит, это означает, что есть страницы, которые посвящены вашим фрагментам кода / инструкций / текста и помечены как незарегистрированные, полностью отделенные от ваших страниц, на которых находятся ваш стек / переменные (где вещи меняются) и помечены как записываемые ?

Да, см. Вывод карты памяти процесса выше. означает читаемый и исполняемый файл,  означает читаемость и запись.

5

2018-03-19 18:47

«Почему это разрешено?» (писать за пределами границ)

C не требует дополнительных инструкций ЦП, которые обычно необходимы для предотвращения этого доступа за пределами диапазона.

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

12

2018-03-19 02:43

Почему это разрешено?

Одной из основных целей дизайна языков C (и C ++) должно быть максимально эффективное время выполнения. Дизайнеры C (или C ++) могли бы принять решение о включении правила в спецификацию языка, в котором говорится, что «запись вне границ массива должна приводить к тому, что X» (где X — это определенное поведение, такое как сбой или брошенное исключение) … но если бы они это сделали, каждый компилятор C был бы обязательный  для создания кода проверки границ для каждого доступа к массиву, который выполняет программа C. В зависимости от целевого оборудования и умения компилятора, применение такого правила может легко сделать каждую программу C (или C ++) в 5-10 раз медленнее, чем она может быть в данный момент.

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

Реальные реализации реализаций теперь свободны делать все, что они хотят — например, в ОС с защитой памяти вы, скорее всего, увидите поведение на основе страниц, как вы описали, или во встроенном устройстве (или на более старых ОС, таких как MacOS 9, MS -DOS или AmigaDOS) компьютер может просто счастливо позволить вам писать в любом месте в памяти, потому что иначе сделать компьютер слишком медленным.

Будучи языком низкого уровня (по современным стандартам), C (C ++) ожидает, что программист будет следовать правилам и будет только механически применять эти правила, если / когда он сможет это сделать, не навлекая на себя служебные расходы.

4

2018-03-19 02:42

Неопределенное поведение ,

Это и есть. Вы Можно  старайтесь писать за пределами, но это не гарантированный  работать. Это может сработать, возможно, нет. То, что происходит, совершенно не определено.

Почему это разрешено?

Потому что это позволяют стандарты C и C ++. Языки предназначены для быстро , Для проверки доступа за пределы доступа потребуется работа во время выполнения, что замедлит работу программы.

Программы для автоматизации торговли, автоматизации ресторанов и кафе

почему этот адрес в p даже доступен для записи?

Это только что произошло  быть. Неопределенное поведение.

Я вижу, что когда я пытаюсь редактировать с большим значением …

Видеть? Опять же, это только что произошло  к segfault.

Когда вызывается malloc, возможно, ОС решает дать процессу целую страницу.

Возможно, но стандарты C и C ++ не требуют такого поведения. Они требуют только, чтобы ОС делала по меньшей мере запрошенный объем памяти, доступный для использования программой. (Если есть доступная память.)

2

2018-03-19 02:36

Просто в C понятие массива довольно элементарно.

Назначение p находится в C так же, как:

и все, что делает компилятор, это:

Во многих архитектурах это реализуется в одной или двух инструкциях.

Обратите внимание, что компилятор не только не знает, что значение 500 не находится в массиве, но и не знает размер массива для начала!

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

Перефразируй. В Pascal компилятор не позволит вам стрелять ногой. В C ++ компилятор предоставляет способы сделать его более трудным для стрельбы по вашей ноге, в то время как в C компилятор даже не знает, что у вас есть нога.

1

2018-03-19 02:42

Это неопределенное поведение …

  • если вы пытаетесь получить доступ к внешним границам, все может случиться, в том числе SIGEGV или коррупция в другом месте стека, из-за чего ваша программа производит неправильные результаты, зависает, падает позже и т. д.

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

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

Почему это разрешилось?

Для этого есть два аспекта:

  • проверка индексов на каждом доступе раздувается (добавляет дополнительные инструкции машинного кода) и замедляет выполнение программы, и, как правило, программист может выполнять некоторую минимальную проверку индексов (например, проверять один раз при вводе функции, а затем использовать индекс, однако, много раз ) или генерировать индексы таким образом, чтобы гарантировать их достоверность (например, цикл от 0 до размера массива)

  • очень точно управляя памятью, так что доступ с ограниченным доступом сообщается с некоторым сбоем процессора, сильно зависит от аппаратного обеспечения и вообще возможен только на границах страниц (например, гранулярность в диапазоне от 1 до 4 тыс.), а также при использовании дополнительных инструкции (будь то в некоторых  функции или в некоторых -wrapping code) и время для оркестровки.

1

2018-03-19 02:41

Популярные вопросы:

Python все комбинации списка списковНужна область карты изображения, нажата, чтобы выбрать соответствующий переключательВызов setVolumeControlStream из службыРазница между BeforeClass и BeforeTest в TestNGiPhone zXing QR Scanner — функция doscanresult никогда не срабатываетJADClipse не работает с Eclipse 3.6syscall variables undefined

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *