Перейти к содержанию
Fire Monkey от А до Я
  • 0

Динамические массивы в FireMonkey


Dmitry Sobko

Вопрос

Добрый день!

Обращаюсь к Вам с проблемой работы в FireMonkey с динамическими массивами.

Ситуация такая, в ходе работы приложения под Android мне необходимо задавать в определенный момент времени размер массива. Функция SetLength почему-то не работает.

Например, если делать так:

procedure TForm1.Button1Click(Sender: TObject);
  var
    Number123 : Array Of Integer;
    i : integer;
begin
   SetLength(Number123, 5);
   for I := 0 to 4 do
     begin
       Number123[i] := i;
     end;
end;

то можно наблюдать следующую ситуацию, что до работы SetLength массив пустой http://joxi.ru/DmBXxLLclDM6AP и это нормально, а после задания длины с массивом происходят странные вещи - вместо ячеек массива какое-то шестнадцатиричное значение http://joxi.ru/823O5xxSYdxl2O, элементы массива по циклу не заполняются.

Если то же самое делать под Windows, то все красиво - http://joxi.ru/gmvR7vvHD3lyma и  http://joxi.ru/Vm6ydxxhYPLXrZ

 

Если под Android сделать так:

procedure TForm1.Button1Click(Sender: TObject);
  var
    Number123 : Array [0..4] Of Integer;
    i : integer;
begin

   for I := 0 to 4 do
     begin
       Number123[i] := i;
     end;

end;

То все работает как надо: http://joxi.ru/KAgKWooTDB84Al

 

Помогите пожалуйста разобраться. Гугл не помогает совсем.

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

Надеюсь на помощь. Спасибо!.

Ссылка на комментарий

Рекомендуемые сообщения

  • 1

Вы путаете две разные ситуации: неправильную работу программы и неправильную работу отладчика (он же дебаггер). 

Думаю, у вас второй вариант, ибо SetLength настолько много где используется, что сбой в её работе давно бы заметили. У меня в проектах для Андроида в XE6 она отрабатывает без проблем.

Некорректная работа отладчика более вероятна, но это, строго говоря, не влияет на поведение готовой программы. 

Ссылка на комментарий
  • 1

Думаю, помимо отладчика здесь есть еще некоторое недопонимание.

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

 

З.Ы. посмотрел скриншоты - мда, отладчик андроида явно недоперестарался :)

Изменено пользователем kami
Ссылка на комментарий
  • 0
31 минуту назад, voytalexey сказал:

Вы путаете две разные ситуации: неправильную работу программы и неправильную работу отладчика (он же дебаггер). 

Думаю, у вас второй вариант, ибо SetLength настолько много где используется, что сбой в её работе давно бы заметили. У меня в проектах для Андроида в XE6 она отрабатывает без проблем.

Некорректная работа отладчика более вероятна, но это, строго говоря, не влияет на поведение готовой программы. 

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

У меня стоит задача кодировать и декодировать сообщения шифрованием RSA. Для работы с большими числами я использую сторонний модуль FGInt http://www.submanifold.be/triade/GInt/gint.html

Этот модуль очень правильно, без погрешностей, производит любые операции с большими числами и в том числе у него есть функционал создания цифровых подписей, кодирования и декодирования информации. Перед тем как выбрать решение для шифрования RSA под Android я много гуглил и много кто ссылался именно на этот модуль. Скачав и изучив его я не нашел ничего такого, что могло бы не работать под Android.

Но к сожалению столкнулся с ситуацией, когда я перевожу строку в число типа FGInt и обратно, то мне возвращается постоянно число 01 вместо 1440294937918237327.

По всем ощущениям баг возникает после использования SetLength. Но я конечно могу ошибаться. 

Может если приложу проект сюда, поможете разобраться? 

Ссылка на комментарий
  • 0

Вот так у меня выглядит запись TFGInt

   TFGInt = Record
      Sign : TSign;
      Number : Array Of LongWord;
   End;

Вот так я пытаюсь перевести из двоичной системы в число

Procedure Base2StringToFGInt(S : String; Var FGInt : TFGInt);
Var
   i, j, size : LongWord;
Begin
   While (S[1] = '0') And (length(S) > 1) Do
      delete(S, 1, 1);
   size := length(S) Div 31;
   If (length(S) Mod 31) <> 0 Then size := size + 1;
   SetLength(FGInt.Number, (size + 1));
   FGInt.Number[0] := size;
   j := 1;
   FGInt.Number[j] := 0;
   i := 0;
   While length(S) > 0 Do
   Begin
      If S[length(S)] = '1' Then
         FGInt.Number[j] := FGInt.Number[j] Or (1 Shl i);
      i := i + 1;
      If i = 31 Then
      Begin
         i := 0;
         j := j + 1;
         If j <= size Then FGInt.Number[j] := 0;
      End;
      delete(S, length(S), 1);
   End;
   FGInt.Sign := positive;
End;

Казалось бы ничего военного, обычная работа с массивами, строками, но в итоге этот код записывает в FGInt.Number значение равное "01"

Изменено пользователем DimeDron
Ссылка на комментарий
  • 0

Прошу прощения за беспокойство. Проблема решена. Ура! :)

Действительно отладчик сбил с толку. voytalexey и kami спасибо Вам большое! На самом деле очень помогли!

Проблема заключалась в нумерации символов в string, например While (S[1] = '0') работает под Windows так как написано, т.е. берет первый символ и проверяет его. В FMX же нужно было написать так While (S[0] = '0'), т.е. первый символ - это нулевой. И как-то странно тогда получается, нет бы для всех операций со строками сделали такое правило, что первый символ - это S[0], когда например delete(S, 1, 1) удаляет именно первый символ, ведь следуя логике должно быть так delete(S, 0, 1). Это тоже сбило с толку.

Еще раз всем большое спасибо!

Если кому нужна будет реализация RSA для Android с использованием FGInt - поделюсь.

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...