Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.06.11;
Скачать: CL | DM;

Вниз

Как отловить 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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.038 c
15-1147634815
Kolan
2006-05-14 23:26
2006.06.11
А как и где выложить Веб приложение


2-1148143099
rar
2006-05-20 20:38
2006.06.11
повысить скорость поиска файлов


15-1147848626
*Pavel
2006-05-17 10:50
2006.06.11
Кто знаком с GSM-bridge ?


15-1147897314
palva
2006-05-18 00:21
2006.06.11
Подарок русским программистам


2-1148232794
Userrrr
2006-05-21 21:33
2006.06.11
можно ли управлять консольным приложением через сеть?