Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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.51 MB
Время: 0.013 c
15-1147704023
Константинов
2006-05-15 18:40
2006.06.11
Вопрос Москвичам


2-1148647797
ADS
2006-05-26 16:49
2006.06.11
Настройка MaskEdit


15-1147899614
fantom423
2006-05-18 01:00
2006.06.11
У кого есть красивые компоненты под базу даных?!!


15-1147762283
Шутник
2006-05-16 10:51
2006.06.11
Обоснование выбора: СУБД vs файлы


2-1148563083
Piero
2006-05-25 17:18
2006.06.11
как работать с ini файлами?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский