
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Сообщ.
#1
,
|
|
|
Имитация движения объекта (точка радиусом 3 пиксела) производится следующим образом: пересчитываются его координаты, на месте его текущего положения перерисовывается фон, сохраненный ранее в его свойстве Bmp, объект отрисовывается в точке с новыми координатами.
Однако, при этом иногда возникает ошибка: floating point invalid operation вот в этом месте программы: Form1.PaintBox1.Canvas.Draw(X-3, Y-3, Bmp); //восстанавливаем фон, извлекая его из свойства Bmp и помещая в текущее месторасположение объекта С чем может быть связана данная ошибка (повторюсь, что возникает она не всегда)? |
Сообщ.
#2
,
|
|
|
Необходимо отметить, что количество объектов, которые отрисовываются, увеличивается за счет создания все новых объектов в цикле. И кроме вышеуказанной ошибки возникает также и другая (а именно project raised exception class EOutOfResources with message 'Out of system resources') в момент отрисовки объекта:
Form1.PaintBox1.Canvas.Pen.Color := clRed; Form1.PaintBox1.Canvas.Brush.Color: =clRed; Form1.PaintBox1.Canvas.Ellipse(X-3, Y-3, X+3, Y+3); |
Сообщ.
#3
,
|
|
|
Ошибка в другом месте
|
Сообщ.
#4
,
|
|
|
Цитата leo @ Ошибка в другом месте Как же его, это место выловить, если выскакивают эти ошибки всегда именно в этих дух местах программы? |
Сообщ.
#5
,
|
|
|
Цитата dimavit @ Как же его, это место выловить Практический совет - учитесь пользоваться отладчиком. И используйте при пошаговом выполнении не только кнопку F8, но и кнопку F7. Теоретические советы вы найдёте в этой статье гуру "Обработка ошибок". Статья довольно большая по объёму, но очень полезная. Советую не только прочитать её вдумчиво, но и сохранить ссылку на неё. Ибо это явно не последняя ошибка в ваших программах. |
Сообщ.
#6
,
|
|
|
Цитата dimavit @ Как же его, это место выловить, если выскакивают эти ошибки всегда именно в этих дух местах программы? Привести больше кода. В частности, ошибка EOutOfResources может возникать как из-за того, что у тебя действительно используется слишком много объектов GDI, а может из-за того, что просто где-то не освобождаются временные объекты, например TBitmap. А ошибка ес-но возникает при создании очередного нового объекта (в данном сл. Pen и Brush). Что казается fp-исключений, то они в x87 вообще генерятся не на самой команде, вызвавшей исключение, а на следующей fp-команде процессора. У тебя вообще вещественные вычисления используются? |
Сообщ.
#7
,
|
|
|
Цитата northener @ Цитата dimavit @ Как же его, это место выловить Практический совет - учитесь пользоваться отладчиком. И используйте при пошаговом выполнении не только кнопку F8, но и кнопку F7. Теоретические советы вы найдёте в этой статье гуру "Обработка ошибок". Статья довольно большая по объёму, но очень полезная. Советую не только прочитать её вдумчиво, но и сохранить ссылку на неё. Ибо это явно не последняя ошибка в ваших программах. Спасибо за ссылку. Навыки отладки, это конечно совершенно необходимо и их явно не хватает. Кстати, не могли бы Вы в этом смысле подсказать, что может означать ошибка, которая указывается в Call Stack: :0040493b @ROUND +$3? Она то и является причиной первой проблемы. А вторую вроде бы побороть удалось. |
Сообщ.
#8
,
|
|
|
Цитата dimavit @ что может означать ошибка, которая указывается в Call Stack: :0040493b @ROUND +$3? То и означает, что при вызове Round округленное вещ.значение не умещается в целый тип и возникает ошибка: floating point invalid operation |
Сообщ.
#9
,
|
|
|
Цитата leo @ Цитата dimavit @ Как же его, это место выловить, если выскакивают эти ошибки всегда именно в этих дух местах программы? Привести больше кода. Код довольно длинный, но логика такая: 1. Имеется динамический массив объектов среди свойств которых находятся их координаты (x и y) и снимок поверхности канвы, перекрываемой данным объектом в текущий момент, и помещаемый туда непосредственно перед самим перемещением в это место. 2. Вначале имеется 2 объекта, но при их столкновении появляются новые объекты, который помещаются в существующий массив и случайным образом задаются их координаты. Таким образом происходит как бы цепная реакция с лавинообразным нарастанием длины динамического массива. 3. Движение происходит в цикле, который сканирует расстояние от первого элемента массива до остальных, потом от второго до остальных и т.д. Расстояние округляется (единственное место где используются нецелые числа), оценивается и, в зависимости от этой оценки, происходят разные события. 4. Визуально отображение движения частиц на экране происходит путем вычерчивания круга в месте нового положения частицы, а на месте ее старого положения канва восстанавливается путем наложения снимка, хранящегося в свойствах объекта. 5. Так вот, при нарастании количества частиц и длины массива, в определенный момент, всегда в одном и том же месте программы, происходит сбой при попытке отрисовки нового положения объекта (Form1.PaintBox1.Canvas.Draw(X-3, Y-3, Bmp)). 6. Можно было бы предположить, что в один и тот же момент разные объекты пытаются обратиться к одному и тому же месту на канве (кто-то читает, кто-то записывает, или одновременно читают, либо записывают), но ведь, насколько я знаю, в случае существования в программе всего одного потока, следующая операция не может начаться до окончания предыдущей. Кроме того, если закомментировать эту строку //Form1.PaintBox1.Canvas.Draw(X-3, Y-3, Bmp) (при этом движение объекта будет оставлять след, поскольку не восстанавливается канва) то остановка происходит ровно на следующей за ней сроке кода if Direction[0] then SetX(Random(Step)*Speed), отвечающей уже за определение направления движения. Код ошибки тот же - floating point invalid operation. 7. Очевидно, что проблема связана с лавинообразным нарастанием количества объектов, однако проявиться она может и при 4, и при 850 элементах, существующих в массиве. Я понимаю, что природа ошибки может быть самой разной, но подскажите хотя бы в каком направлении необходимо копать. Спасибо. |
Сообщ.
#10
,
|
|
|
Разделяй и властвуй )
ищи отсекая не нужное {} или (* *) или // Ну и хорошо выложить, то что выдаёт ошибку) Чтобы не напрягать телепатические способности ![]() |
Сообщ.
#11
,
|
|
|
Цитата dimavit @ Я понимаю, что природа ошибки может быть самой разной, но подскажите хотя бы в каком направлении необходимо копать. "Природа" м.б. разной, но источником fp-invalid-op являются 1) вызов sqrt(x) при x < 0 2) i:=round(x) или trunc(x), при x > High(i) или x < Low(i) 3) экзотические ситуации неправильной работы со стеком FPU (возможны только при собственных косяках при использовании встроенного асма) Поэтому, если у тебя ф-я round вызывается в одном месте, то вставь перед ней проверку вещ.числа на допустимый диапазон: ![]() ![]() d:=...; //расчет вещественного расстояния if (d >= Low(di) and (d < High(di)) then di:=round(d) else di:=0; //<-- поставь брикпойнт на эту строку Если брик сработает, то смотри чему равно d и другие переменные, из которых оно высчитывалось Добавлено PS: Можно конечно просто поставить условный брик на строку с round, но работать это будет о-о-очень долго |
Сообщ.
#12
,
|
|
|
Кстати EInvalidOp также генерируется при вещественном делении 0/0 - скорее всего это и есть источник ошибки при попытке вычисления нулевого расстояния между совпадающими точками. В этом случае ошибка как раз генерируется не на самой команде деления, а на следующей fpu-команде. Поэтому, если затем вызывается Round, то ошибка возникает на первой же команде fistp по адресу @ROUND+$3, а не на второй fwait @ROUND+$6, как было бы в случае невозможности преобразовать вещ.число в Int64
|
Сообщ.
#13
,
|
|
|
Цитата leo @ Кстати EInvalidOp также генерируется при вещественном делении 0/0 - скорее всего это и есть источник ошибки Спасибо, огромное. Именно так оно и было. Одной проблемой стало меньше. |