Simple-Scada forum

Simple-Scada 2 => Ваши вопросы => Тема начата: Серега от 19 Февраля 2025, 15:02:01

Название: Массивы и работа с ними
Отправлено: Серега от 19 Февраля 2025, 15:02:01
Добрый день!
Итак вводные данные.
Согласно темам с форума объявляем и инициализируем статический массив в глобальном модуле (3ий по счету, когда то Вы писали, что так делать можно).
например такой:
Код: (delphi)
interface
var
  MinArrayNamesObjects: array[1..2] of string = (
    'человек',
    'автомобиль'
   );

  ArrayNamesObjects: array[1..4] of string = (
    'человек',
    'велосипед',
    'автомобиль',
    'кошка'
  );
На мнемосхеме выставляем элемент Текст (например с именем Camera1Text).
Заводим новый скрипт по изменению переменной например IDObject тип LongWord.
Текст скрипта ниже.
Код: (delphi)
begin
  Camera1Text.Text := ArrayNamesObjects[IDObject.AsInt];
end.
Ошибок компиляции нет, проект сохраняется без ошибок.
Запускаем клиента и тут...
При попытке перейти на страницу с элементом Camera1Text клиент просто делает переподключение к серверу. Все остальное работает.
Подозрение на новые введения. Сравнение указывает только на глобальный модуль и скрипт. Комментируем скрипт, перезагрузка проекта и - все работает в штатном режиме.
В журнале ни каких аварийных записей.
Повторил эту же ситуацию на локальном ноуте в простом проекте. Все то же самое "Соединение с сервером было разорвано" и потом подключение.
Можете проверить у себя.
Название: Re: Массивы и работа с ними
Отправлено: Simple-Scada от 19 Февраля 2025, 16:14:14
Здравствуйте.

Здесь и без проверки причина понятна. У Вас массив начинается с единицы: [1..2]. В скрипте Вы обращаетесь через ArrayNamesObjects[IDObject.AsInt]. Все целочисленные переменные имеют начальное значение равное 0. Т.е. Вы пытаетесь получить нулевой элемент массива, которого не существует и в результате обращаетесь к несуществующей памяти. Последствия такого кода будут непредсказуемыми. При работе с массивами проверяйте на индексы, например:
Код: (delphi)
var
  aIndex: Integer;
begin
  aIndex := IDObject.AsInt;
  if (aIndex >= Low(ArrayNamesObjects)) and (aIndex <= High(ArrayNamesObjects)) then
    Camera1Text.Text := ArrayNamesObjects[aIndex];
end.

Компилятор конечно не выдал ошибок, т.к. он не может предсказать, к какому элементу массива будет обращение во время работы. Если Вы хотите, чтобы проверки делала скада и выдавала ошибки при обращении к несуществующим элементам, то НЕ работайте с памятью напрямую (через массивы, или указатели), а используйте списки, как описано по ссылке (https://simple-scada.com/help/script/stringlist.html). Пример:
Код: (delphi)
var
  MinArrayNamesObjects: TM_StringList;

implementation

initialization
  // создаём список строк
  MinArrayNamesObjects := TM_StringList.Create;
  // заполняем список. Можно заменить на загрузку строк из
  // файла, чтобы не перечислять строки в скрипте
  MinArrayNamesObjects.Add('человек');
  MinArrayNamesObjects.Add('автомобиль');

finalization
  // очищаем память выделенную под список
  FreeAndNil(MinArrayNamesObjects);

end.