2015-10-19 3 views
3

В VCL, TByteDynArray определяется как динамический массив:Почему доступ к индексам за пределами границ динамического массива не повышает AV?

type TByteDynArray = array of Byte; 

Но мне кажется, что индекс оценки проверка не выполняется:

var 
    DataBytes: System.Types.TByteDynArray; 
    i: Integer; 
begin 
    SetLength(DataBytes, 2); 
    DataBytes[5] := 222; // Accessing index beyond set length. 
    i := DataBytes[5]; // `i` is now set to "222". 

Код выше работает без ошибок.

Почему нет AccessViolation поднятых, как со статическим массивом? Какова точка SetLength, если вы можете получить доступ и изменить 65536 байт памяти переменной массива независимо от установленной длины?

+1

диапазона по умолчанию отключена; используйте '$ r +', чтобы включить его – fantaghirocco

+1

* Приведенный выше код работает без ошибок. * Возможно. Возможно, нет. Независимо от того, есть или нет, ошибка не предсказуема. –

+0

@DavidHeffernan Из теста, который я сделал, он воспроизводимо не вызывает ошибки. Какую ошибку можно было бы повысить? – DBedrenko

ответ

6

Чтобы обнаружить ошибки индекса массива вне границ, установите ошибку проверки диапазона.

Range Checking

директива $ R включает или отключает генерацию диапазона проверки кода. В состоянии {$ R +} все выражения в массиве и строковых индексах проверяются как находящиеся в пределах определенных границ, и все назначения для скалярных и поддиапазонных переменных проверяются в пределах диапазона. Если проверка диапазона не выполняется, возникает исключение ERangeError (или программа завершается, если обработка исключений не включена).

По умолчанию установлено значение {$ R-}, но я предлагаю установить его, по крайней мере, на этапе разработки. Он добавляет дополнительные накладные расходы на код, так что это может быть причина, по которой он отключен по умолчанию.


Если у вас есть блок, который хорошо проверен и хотите, чтобы избежать проверки диапазона, добавьте {$ R-} в верхней части устройства. Это будет переопределять настройку проекта локально.

Если вы хотите, чтобы избежать проверок диапазона в блоке коды, этот метод может быть использован: проверка

{$IFOPT R+} 
    {$DEFINE RestoreRangeCheck} 
    {$R-} 
{$ENDIF} 

{- Some code here } 

{$IFDEF RestoreRangeCheck} 
    {$R+} 
    {$UNDEF RestoreRangeCheck} 
{$ENDIF} 
+0

Благодарим вас за полезный ответ. Не могли бы вы дать некоторые рекомендации относительно того, следует ли мне включить это (вместо того, чтобы делать явные проверки диапазона в коде)? Почему это не по умолчанию? – DBedrenko

+2

@NewWorld Вы должны * всегда * запускать проверку диапазона и проверку переполнения (по крайней мере, в вашей конфигурации отладки). Сделайте это по умолчанию для IDE. Почему это не по умолчанию, бьет меня.Глупое дизайнерское решение IMO –

+1

Это не так, потому что люди обычно определяют массив как 'a = array [0..0] integer' и динамически назначают (большой блок) памяти для него. Смотрите большую часть VCL. В таком сценарии вы не хотите '{$ R +}'. Однако это действительно должно быть по умолчанию. – Johan

 Смежные вопросы

  • Нет связанных вопросов^_^