Arhn - архитектура программирования

ERangeError в Delphi XE

Я переношу программное обеспечение с Delphi 5 на Delphi XE. Я уже исправил много различий и теперь могу скомпилировать свой код.

Проблема в том, что иногда (в некоторых местах кода) я получаю сообщение об ошибке "Ошибка проверки диапазона".

Например, в этом коде:

function CopyChar(Ori : string; var Des : Array of char) : Boolean;
var Msg     : string;
    Counter : integer;
    SizeDes : integer;
begin
    SizeDes:= SizeOf(Des);
    for Counter:= 1 to SizeDes do begin
        Des[Counter-1]:= ' ';
    end;
    Ori:= Trim(Ori);
    Msg:= '';
    SizeDes:= Min(Length(Ori),SizeDes);
    for Counter:= 1 to SizeDes do begin
        Des[Counter-1]:= char(Ori[Counter]);
    end;
    CopyChar:= True;
end;

Я получаю ошибку во время выполнения при прохождении строки Des[Counter-1] := ' '; Ошибка возникает не при первом прохождении цикла, а через много раз.

Я пытался отключить Rance Checking ($R), но это не решает мою проблему. Я также пытался изменить тип «Счетчик» на Cardinal и LongWord, но безуспешно.

Буду рад любой полезной идее!

Спасибо.

18.01.2011

  • Вместо того, чтобы описывать это как остановку после большого количества раз, будьте точны. Используйте отладчик, чтобы точно узнать, сколько раз вы проходите цикл. Это должно было быть одним из первых вопросов, которые вы задали себе, когда увидели, как он рухнул. Все ли переменные имеют ожидаемые значения? Если нет, то чем они отличаются? Почему вы ожидали, что они будут иметь те же ценности, что и вы, и как вместо этого они получили другие ценности? 18.01.2011

Ответы:


1

Код должен выглядеть примерно так:

function CopyChar(Ori : string; var Des : Array of char) : Boolean;
var Msg     : string;
    Counter : integer;
    LenDes  : integer;
begin
    LenDes:= Length(Des);
    for Counter:= 1 to LenDes do begin
        Des[Counter-1]:= ' ';
    end;
    Ori:= Trim(Ori);
    Msg:= '';
    LenDes:= Min(Length(Ori),LenDes);
    for Counter:= 1 to LenDes do begin
        Des[Counter-1]:= char(Ori[Counter]);
    end;
    CopyChar:= True;
end;

Я предполагаю, что ваша проблема связана с тем, что Char теперь имеет ширину 2 байта (в Delphi 5 он был шириной 1 байт), хотя я никогда не использовал SizeOf для открытого массива и даже не знаю, что он делает!

Есть несколько других проблем с этим кодом. Возвращаемое значение кажется немного бессмысленным, поскольку оно может возвращать только True. Это также может быть несколько сжато, например:

procedure CopyChar(Ori: string; var Des: array of char);
var
  i: Integer;
begin
  Ori := Trim(Ori);
  for i := 1 to Length(Des) do begin
    if i<=Length(Ori) then
      Des[i-1] := Ori[i];
    else
      Des[i-1] := ' ';
  end;
end;
18.01.2011
  • Вы не можете использовать динамический массив в приведенном выше коде; Аргумент Des представляет собой статический массив, и SizeOf(Des) = Length(Des) * SizeOf(Char); 18.01.2011
  • @Serg Моя ошибка, я, конечно, должен был написать open array, и я это исправил. На самом деле вы можете передать этой функции динамический массив. 18.01.2011
  • Нет, вы не можете передать динамический массив символов как открытый массив, по крайней мере, это невозможно в Delphi 2009 - см. stackoverflow.com /вопросы/3781691/ 18.01.2011
  • @Серг, я исправлен. Я наивно предположил, что вы можете сделать это, потому что вы можете сделать это для несимвольных типов. Я никогда не сталкивался с этим, потому что, естественно, я не использую открытые массивы типов символов. 18.01.2011
  • Спасибо, это решило ERangeError, но в результате я получил странные символы (в виде маленьких квадратиков). Итак, мне пришлось изменить весь массив Char, заменив их массивом AnsiChar. 18.01.2011
  • @Marcela Трудно понять, что здесь происходит, не видя, что находится по другую сторону CopyChar. Но мне кажется, что вам нужно немного почитать об изменениях Unicode, внесенных в современный Delphi. Взгляните на статью Марко Канту по этому вопросу: edn.embarcadero.com/article/38980. 18.01.2011
  • И вы можете прочитать о разнице между Length(x) и Sizeof(x). Длина сообщает вам количество элементов в массиве. Sizeof сообщает вам количество байтов в типе. 19.01.2011
  • @Warren Чтобы процитировать документацию, возвращает количество байтов, занимаемых переменной или типом. В этом случае OP использует его для переменной, а не для типа. 19.01.2011

  • 2

    Другой проблемой может быть поврежденный ввод Ori или Des, поэтому, если проблема не решена решением Дэвида, вам также следует проверить код вызова.

    18.01.2011
  • Исходная проблема заключается в том, что SizeOf использовался вместо длины, а SizeOf возвращает 2 * длина, когда массив представляет собой Char, теперь, когда Char имеет ширину 2 байта. И почему это эффективнее? 18.01.2011
  • Конечно, но не обязательно единственная проблема. Это более эффективно, поскольку сравнение выполняется не для каждой итерации цикла. Это не учитывает того, что делает оптимизатор, признаюсь, я не читал сгенерированный ассемблерный код ;) 18.01.2011
  • Вряд ли оно того стоит, учитывая, что код становится сложнее читать и проверять! Скорее всего, производительность здесь не будет узким местом. И в любом случае ваш код действительно выполняет сравнение на каждой итерации цикла, и он не завершается правильно, поскольку проверки ‹ должны быть ‹=. Так что я думаю, что быстрее не пойдет, и это неправильно. Это хороший пример того, что делает преждевременная оптимизация! 18.01.2011
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..