Войти
ПрограммированиеФорумОбщее

Работа с указателями в Delphi

Страницы: 1 2 3 4 Следующая »
#0
13:42, 16 апр. 2012

Уважаемые программисты! Обнаружил такую особенность в работе программы. Есть список, в который записаны указатели на частицы.

  TFragment = record
    position, speed, direction : TD3DVector;
    life, scale, fps_dis       : single;
    state                      : boolean;
    color                      : TRGBA;
  end;

  PFragment = ^TFragment;

Каждая частица существует определенное время, после чего state меняется на false

Когда срабатывает таймер, программа перебирает список и ищет частицу с state=false. Если таковая есть, частица перезапускается. В ином случае создается новая частица:

procedure TPowerEngine.launch_fragment;
var
  i     : integer;
  fragm : PFragment;
  flag  : boolean;
begin
  flag := false;

  if (objects.Count > 0) then
    for i := 0 to objects.Count - 1 do begin
      fragm := objects.Items[i];

      if (not fragm.state) then begin
        RestartFragment(fragm);        
        flag := true;
        break;
      end;

    end;

  if (not flag) then begin
    new(fragm);
    RestartFragment(fragm);
    objects.Add(fragm);
  end;
end;

В листинге есть вызов RestartFragment(fragm). Вот эта процедура:

procedure TPowerEngine.RestartFragment(var fragm_ : PFragment);
var
  r_vector : TD3DVector;
begin
  fragm_.position := position;

  fragm_.life := 0.0;
  fragm_.state := true;
  fragm_.scale := scale;
  fragm_.fps_dis := dis_3d(fragm_.position, v_points.pnt1);

//дальше заполнение других полей - не так важно
end;

Одним словом, строчка

fragm_.position := position;

(position - поле объекта TPowerEngine) глючит. Это проявляется в некорректном подсчете поля life частицы после ее перезапуска (т.е. когда перебирается список, ищется частица со state=false и она перезапускается). Если убираю эту строчку, работа программы меняется, чего, вообще-то быть не должно.

Хотелось бы услышать некоторые идеи относительно этого глюка.


#1
14:57, 16 апр. 2012

В коде явных ошибок не видно. И непонятно что ты хотел сказать "глючит. Это проявляется в некорректном подсчете поля life частицы после ее перезапуска". Так что нужны дополнительные сведения что глючит конкретно и как.
Так же замечу что fragm_ передаётся как var - это судя по коду не нужно делать, не ошибка, но неэффективность. Достаточно просто передать указатель как есть.

#2
20:43, 16 апр. 2012

может, в цикле обработки частиц ошибка( например обрабатываются частицы с state= false)?
А идеально было  бы если б готовый пример  можно было скачать и откомпилировать.

#3
21:33, 16 апр. 2012

что глючит конкретно и как

Создается частица. Поле life увеличивается каждый такт: 0    0.1      0.2        0.4  и т.д. до 2.0 секунд. После этого state меняется на false и частицы до перезапуска обновляться не должны. Там есть проверка типа

if fragm_.state then update_fragment(fragm_);

Дальше постепенно происходит перезапуск частицы. После этого поле life (я контролировал 4-ю частицу) меняется: 1.7      1.8        1.7  и т.д. Либо как 0.2  0.3  0.2 и т.д. Хотя при перезапуске поле life обнуляется.

Иными словами, строчка

fragm_.position := position;

меняет результат работы объекта со списком частиц. Точнее, влияет на содержимое полей записей.

Закрываю эту строчку кавычками, и поле life 4 частицы начинает на любом перезапуске меняться от 0 до 1 и 2 сек. Т.е. как и следует.

Выкладывать пример полностью сложно - это часть большой программы.

Обсуждаемый код достаточно простой, если не считать, что объект юзает принадлежащий ему список.

Пробовал проверять работу алгоритма со списком, указанным в var основной программы, вслед за описанием основной формы. Использовал 2 таймера (стандартных) - 1 для плюсования жизни частицам, второй - для переодического их запуска. Работает безупречно.

Я несколько часов сегодня проверял этот код. Явных и формальных ошибок нет.
Все-таки Delphi иногда глючит. Как и любая программа.

#4
21:51, 16 апр. 2012

old_proger
> Я несколько часов сегодня проверял этот код. Явных и формальных ошибок нет.
> Все-таки Delphi иногда глючит. Как и любая программа.

Это говорит лишь о том, что вы начинающий писатель.
В данном контексте Delphi это не программа (среда разработки), а именно компилятор!

Вы даже не назвали версию компилятора Delphi, а уже говорите о баге.

#5
22:27, 16 апр. 2012

old_proger
> Все-таки Delphi иногда глючит
Ну да, прям 2+2 не может сложить ) Ищите ошибку у себя
Я не вижу, где там созданные (через new) fragm удаляются
И почему обрабатываете только одну "умершую" частицу в списке

#6
7:26, 17 апр. 2012

old_proger
> Все-таки Delphi иногда глючит. Как и любая программа.

))))
Даю 99.999% что дело не в дельфи.

Вообще поведение довольно странное - но тем и интереснее найти какой участок кода и как её создаёт.
Вообще может быть какая нибудь абсолютная банальщина типа кусочка забытого тестового кода модифицирующего state-ы и life-ы.
Еще может быть незначительная порча хипа, хотя обычно порча хипа приводит к крашу.
В общем надо отлаживать.

#7
12:36, 17 апр. 2012

old_proger
ещё раз повтори пожалуйста
какое поле трётся
и на какой команде

#8
13:52, 17 апр. 2012

Ошибка в другом месте.

У меня так тоже бывает, либо на время закомментирую, либо допишу тестовый участок, про который забуду, и это портит малину.

#9
14:18, 17 апр. 2012

old_proger
> Работа с указателями в Delphi
Не, не слышал.

#10
22:59, 17 апр. 2012

Aslan
> Я не вижу, где там созданные (через new) fragm удаляются
А зачем их там удалять? Они повторно используются.

#11
17:25, 19 апр. 2012

Aslan
Ищите ошибку у себя
Искал. Долго искал. Но конкретный кусок кода достаточно простой и ... в общем выше все написано.

acDev
вы начинающий писатель
Мне трудно себя сравнивать с Джоном Кармаком

acDev
версию компилятора Delphi
7 Delphi 2003 г.

acDev
уже говорите о баге
Я говорил - делаю комментарием одну строку (это присваивание позиции частице в начальный момент времени), и плюсование life частицам идет совсем по другому. Разве это не глюк?

cyborg
Ошибка в другом месте
Очень возможно. Иногда глючит - а причина в том, что десятью строками выше поставили (не поставили) необязательную в данном случае точку с запятой, и компилятору это не нравится.

В общем, глюк некритичный. Частиц много, и система в целом отрисовывается сносно. Хотя с другой стороны, всегда стоит стремиться к 100% ясности и правильности работы программы. Не собираюсь ругать Delphi. Глюки - плата за сложность программ. Всем спасибо за советы и мнения.

Тема закрыта.

#12
18:04, 19 апр. 2012

{$O-} пробовал? Я неоднократно сталкивался с ошибками оптимизатора в делфи7. Выглядело приблизительно как у тебя — элементарный код отрабатывал некорректно.

#13
18:33, 19 апр. 2012

>>RestartFragment(var fragm_ : PFragment);
Можно поинтересоваться какой смысл передавать указатель с директивой var? Там указатель меняете где-то? Может в этом и ошибка. Не видя полного кода, а только кусочки, которые Вы посчитали важными, сложно что-то диагностировать. Но вот var тут точно лишний.

#14
22:40, 19 апр. 2012
procedure TPowerEngine.RestartFragment(var fragm_ : PFragment);
...
fragm_.position := position;
...

1. При работе с указателем его не надо передавать как var
2. при доступе к полям записи через указатель его надо-бы разадресовывать:

fragm_^.position := position;

3. переменные-указатели называй как-то осмысленней, типа так: pFragm: PFragment

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.