Форум: "Прочее";
Текущий архив: 2006.06.11;
Скачать: [xml.tar.bz2];
ВнизКак отловить Stack overflow Найти похожие ветки
← →
Andy BitOff © (2006-05-16 13:00) [0]При рекурсии иногда вываливается Stack overflow, при этом, если в месте вылета поставить
try
...
except
on E: EStackOverflow do DrawError();
end;
то Stack overflow нет, а вываливается в дебагер (если из под IDE запускать) или вываливается без сообщений, просто закрывается (если запускать непосредственно ехе). При этом брэкпоинт на except"е не срабатывает.
← →
Desdechado © (2006-05-16 13:04) [1]если стек переполнился, то гаплык :)
вызов других процедур по обработке ошибки только усугубит (они ведь тоже стек используют)
увеличь в параметрах проекта размер стека
но, имхо, лучше замени чем-нибудь рекурсию
← →
Andy BitOff © (2006-05-16 13:10) [2]Desdechado © (16.05.06 13:04) [1]
вызов других процедур по обработке ошибки только усугубит (они ведь тоже стек используют)
Хм. Логично. А зачем тогда вообще EStackOverflow, если по теории его не обработать, ведь в момент его возникновения (возможно) стэк уже переполнен.
← →
MBo © (2006-05-16 13:13) [3]Видимо, неверно организована рекурсивная процедура - плохое условие останова, слишком большой объем локальных переменных и т.д.
Показывай.
← →
Andy BitOff © (2006-05-16 13:20) [4]
procedure Tfrm_Details.PassingPixel(x, y: integer);
///////////
function DrawPixel(x, y: integer): boolean;
var
aRect: TRect;
begin
aRect :=Rect(0, 0, qSource1.Width-1, qSource1.Height-1);
Result := PixelInRect(x, y, aRect) and
((GetPixel(qDest, x, y) <> 255) and
((GetPixel(qSource2, x, y) = 255) or (GetPixel(qSource1, x, y) = 255)));
end;
/////////////
begin
qDest.SetPixel(x, y, clWhite);
if DrawPixel(x, y + 1) then PassingPixel(x, y + 1);
if DrawPixel(x + 1, y + 1) then PassingPixel(x + 1, y + 1);
if DrawPixel(x + 1, y) then PassingPixel(x + 1, y);
if DrawPixel(x + 1, y - 1) then PassingPixel(x + 1, y - 1);
if DrawPixel(x, y - 1) then PassingPixel(x, y - 1);
if DrawPixel(x - 1, y - 1) then PassingPixel(x - 1, y - 1);
if DrawPixel(x - 1, y) then PassingPixel(x - 1, y);
if DrawPixel(x - 1, y + 1) then PassingPixel(x - 1, y + 1);
end;
qSource1, qSource2, qDest: TQuickPixels; - скоростной доступ к битмапу, в сущности битмап.
← →
Desdechado © (2006-05-16 13:24) [5]не совсем понял смысл операций
это что, отрисовка клубящегося дыма?
а циклом заменить нельзя?
← →
Andy BitOff © (2006-05-16 13:44) [6]Desdechado © (16.05.06 13:24) [5]
а циклом заменить нельзя?
Не знаю, не пробовал =) При обдумывании алгоритма сразу остановился на таком варианте.
Desdechado © (16.05.06 13:24) [5]
не совсем понял смысл операций
Например.
На qSource1 есть точка
на qSource2 круг залитый
Если точка попадет в круг, то на qDest попиксельно перерисуется весь круг.
Пример очень, повторяю очень грубый, т.к. qSource1 и qSource2 могут содержать кучу всевозможных, даже не фигур, а ..., короче наборов связаных и не связаных пикселей. И при совпадении их на обоих на qDest перерисовывается or обоих.
Короче, сейчас может залью два изображения куда-нибудь, посмотрите.
← →
Andy BitOff © (2006-05-16 13:51) [7]Вот, если интересно.
http://bitoff.pisem.net/temp/s1.jpg - qSource1
http://bitoff.pisem.net/temp/s2.jpg - qSource2
http://bitoff.pisem.net/temp/result.jpg - qDest
А вообщем, ладно, это происходит при известных причинах, просто сделаю счетчик входа в процедуру и буду генерить ошибку.
← →
MBo © (2006-05-16 13:52) [8]Для вполне нормальных размеров картинок порядка пикселов стек иногда может расти до миллиона вызовов, что дает десятки мегабайт стекового пространства!
Кроме того, процедуры сильно неоптимальны - на каждом шаге формируется прямоугольник - а достаточно сделать это один раз до начала, да и проверка на вхождение в прямоугольник избыточна - нужно для шаго влево проверять только, что X>0 и т.д.
А вообще, поищи в инете алгоритмы заливки (у тебя - восьмисвязная).
Использованный метод прост, но сильно неоптимален.
Есть рекурсивные методы с глубиной стека порядка N (картинки), а не N^2, как здесь, и другие методы...
Вот одна из ссылок:
http://algolist.manual.ru/graphics/fill.php
← →
MBo © (2006-05-16 13:53) [9]пардон:
нормальных размеров картинок порядка 1000 пикселов
← →
Andy BitOff © (2006-05-16 14:06) [10]Да, я уже сообразил. В основном это происходит на больших картинках 640х480 и при выборе метода бинаризации, который использует FineReader, что в данном случае не эффективно, т.к. там алгоритм заточен под текст и результат получается, мягко говоря, не точный, а именно иногода даже просто белая картинка. А вот, с другими бинаризациями этого на происходит.
Вообщем спасибо, одна голова хорошо, а несколько лучше, вот я и пришел к решению.
Наверное, на данном этапе не буду углубляться в изучение предложенного Вами материала, из-за недостатка времени, но в будущем обязатель проштудирую, спасибо. А сейчас все-таки обойдусь счетчиком.
← →
TUser © (2006-05-16 14:28) [11]Оформи все это циклом. Не надо использовать рекурсию, там где не надо.
while true do begin
if DrawPixel(x, y + 1) then inc (y) else
if DrawPixel(x + 1, y) then inc (x) else
...
if ... then ... else
break;
end;
← →
MBo © (2006-05-16 14:47) [12]>TUser © (16.05.06 14:28) [11]
Сэр, да вы закоренелый рекурсофоб! ;)
В выбранной парадигме без рекурсии, циклом, подобным приведенному, не обойти всю область с закоулками (ну или свой стек придется делать для возврата)
← →
TUser © (2006-05-16 14:52) [13]Ой, я действителньо ерунду написал.
← →
Andy BitOff © (2006-05-16 14:53) [14]А я вот, сейчас под душем стоял, ну, и простите мне мою непроходимость, но так и не смог продумать, как это реализовать в цикле.
Это, наверное, мзвечная борьба, как с использованием goto =)
← →
Vendict © (2006-05-16 22:25) [15]А если банально предоставить оптимизатору сделать из рекурсии цикл ? или он так же не справляется ?
← →
Andy BitOff © (2006-05-16 22:30) [16]Это как?
← →
WondeRu © (2006-05-17 08:52) [17]"Чтобы понять рекурсию, надо понять рекурсию!" (с) студенческое
← →
WondeRu © (2006-05-17 08:53) [18]Кстати, а есть хоть примерные способы, шаблоны обхода рекурсий циклами или другими конструкциями? Где-нибудь это описано?
← →
MBo © (2006-05-17 09:23) [19]>WondeRu © (17.05.06 08:53) [18]
>Кстати, а есть хоть примерные способы, шаблоны обхода рекурсий циклами или другими конструкциями? Где-нибудь это описано?
У Стивенса в книге есть кое-что, у Вирта, да и в других талмудах по алгоритмам. Концевая (tail) рекурсия элементарно удаляется, а вот с многократными рек. вызовами - обычно сложнее.
← →
WondeRu © (2006-05-17 10:21) [20]гляну у них!
← →
WondeRu © (2006-05-17 10:30) [21]"На самом деле любую рекурсивную функцию можно преобразовать таким образом, чтобы все рекурсивные вызовы в ней были концевыми. В некоторых случаях такое преобразование делается очень просто, в других случаях требуется глубокий анализ функции."
http://akoub.narod.ru/funcbook/chapter2/c2.htm
только примеры тут на Haskell :) Не знаю я его :)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2006.06.11;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.01 c