[gelöst] Maximale Rekursionstiefe?
[gelöst] Maximale Rekursionstiefe?
Hallo,
ich habe eine Methode, die sich (für die Ausübung ihres Zwecks) rekursiv aufruft. Ich durchlaufe damit Bilder (Typ: QImage). Es wird beim Bildmittelpunkt begonnen. Sind die Bilder klein genug, so verläuft alles wie gewünscht. Um die Funktion aber auf ihr "Können" zu prüfen, habe ich ein Bild im Format 800x600 genommen. Dieses Bild ist komplett weiß und soll einfach schwarz gemacht werden. Dabei schmiert mir das Programm mit einem Segmentation fault ab. Ich habe daraufhin einen Zähler hinzugenommen. Mit diesem limitiere ich die Rekursionstiefe auf einen festen Wert. Ergebnis: Kein Segmentation fault, das Programm läuft.
Ich habe dunkel in Erinnerung, dass bei der Rekursion so einiges zwischengeparkt wird, um es zum geeigneten Zeitpunkt wieder weiterzuverwenden. Ich nehme an, es liegt derweil auf dem Stack. Da der von System zu System meines Wissens nach unterschiedlich ist, denke ich, dass ich mit meinem fixen Limit auf dem einen System mehr Glück habe als auf einem anderen.
Welche Möglichkeiten gibt es hierzu keinen konstanten Wert zu nehmen?
Gruß,
gelignite
ich habe eine Methode, die sich (für die Ausübung ihres Zwecks) rekursiv aufruft. Ich durchlaufe damit Bilder (Typ: QImage). Es wird beim Bildmittelpunkt begonnen. Sind die Bilder klein genug, so verläuft alles wie gewünscht. Um die Funktion aber auf ihr "Können" zu prüfen, habe ich ein Bild im Format 800x600 genommen. Dieses Bild ist komplett weiß und soll einfach schwarz gemacht werden. Dabei schmiert mir das Programm mit einem Segmentation fault ab. Ich habe daraufhin einen Zähler hinzugenommen. Mit diesem limitiere ich die Rekursionstiefe auf einen festen Wert. Ergebnis: Kein Segmentation fault, das Programm läuft.
Ich habe dunkel in Erinnerung, dass bei der Rekursion so einiges zwischengeparkt wird, um es zum geeigneten Zeitpunkt wieder weiterzuverwenden. Ich nehme an, es liegt derweil auf dem Stack. Da der von System zu System meines Wissens nach unterschiedlich ist, denke ich, dass ich mit meinem fixen Limit auf dem einen System mehr Glück habe als auf einem anderen.
Welche Möglichkeiten gibt es hierzu keinen konstanten Wert zu nehmen?
Gruß,
gelignite
Zuletzt geändert von gelignite am 17. September 2008 22:53, insgesamt 1-mal geändert.
{brigens ist ein Kezboard/Treiber v;llig [berfl[ssig!
Re: Maximale Rekursionstiefe?
Dann fehlt irgendwo eine Pointerüberprüfung. Die max. Rekursionstiefe ist natürlich auf jedem Rechner unterschiedlich, deshalb nutzt ein statischer Wert hier gar nichts. Nimm lieber einen Debugger und schau wo der Absturz stattfindet.gelignite hat geschrieben:Dabei schmiert mir das Programm mit einem Segmentation fault ab.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
Re: Maximale Rekursionstiefe?
Deine Erinnerung täuscht dich nicht.. die Limite ist compilerabhängig.. also entweder steuerst du die Limite (stack-size) per Compiler-Flag (schlechte Variante) oder du löst das Problem iterativ anstatt rekursiv (gute Variante).gelignite hat geschrieben: Welche Möglichkeiten gibt es hierzu keinen konstanten Wert zu nehmen?
Re: Maximale Rekursionstiefe?
An welcher Stelle genau? Ich scheine den Wald vor lauter Bäumen nicht zu sehen. Das ist die Methode:macman hat geschrieben:Dann fehlt irgendwo eine Pointerüberprüfung.gelignite hat geschrieben:Dabei schmiert mir das Programm mit einem Segmentation fault ab.
Code: Alles auswählen
void BLOB::fill( QImage & image, const int & width, const int & height,
int x, int y, uchar & newval, int & depth )
{
// Don't decend too deep
if ( depth > 100000 ) // So klappt es. Wird der Teil aber auskommentiert, kommt es zum SegFault.
return;
// Change color to not to touch a pixel twice
image.setPixel( x, y, newval );
// Upwards
if ( y > 0 )
if ( qGray( image.pixel( x, y - 1 ) ) == _white )
{
depth++;
this->fill( image, width, height, x, y - 1, newval, depth );
depth--;
}
// Rightwards
if ( x < width - 1 )
if ( qGray( image.pixel( x + 1, y ) ) == _white )
{
depth++;
this->fill( image, width, height, x + 1, y, newval, depth );
depth--;
}
// Downwards
if ( y < height - 1 )
if ( qGray( image.pixel( x, y + 1 ) ) == _white )
{
depth++;
this->fill( image, width, height, x, y + 1, newval, depth );
depth--;
}
// Leftwards
if ( x > 0 )
if ( qGray( image.pixel( x - 1, y ) ) == _white )
{
depth++;
this->fill( image, width, height, x - 1, y, newval, depth );
depth--;
}
}
Now filling ...
*** Process aborted. Segmentation fault ***
Es funktioniert wie erwähnt aber, wenn ich die Rekursionstiefe limitiere.
Die iterative Lösung würde mir auch besser gefallen, aber eine iterative Lösung dazu (siehe Code oben) kenne ich nicht.solarix hat geschrieben:oder du löst das Problem iterativ anstatt rekursiv (gute Variante)
Das Bild soll nicht pixelweise durchlaufen werden, sondern zusammenhängende Teile sollen damit befüllt werden. (Quasi, wie die Tintenfass-Funktionalität aus Zeichenprogrammen).
Gruß,
gelignite
{brigens ist ein Kezboard/Treiber v;llig [berfl[ssig!
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Startposition in QQueue.
while (QQueue not empty) {
Position aus QQueue holen.
if (!Wurde die Position bereits bearbeitet) {
Position bearbeiten
if (Wurde die Position links davon bereits bearbeitet) {
Linken Punkt in die QQueue
}
if (Wurde die Position rechts davon bereits bearbeitet) {
Rechten Punkt in die QQueue
}
// dito rechts und links...
}
}
while (QQueue not empty) {
Position aus QQueue holen.
if (!Wurde die Position bereits bearbeitet) {
Position bearbeiten
if (Wurde die Position links davon bereits bearbeitet) {
Linken Punkt in die QQueue
}
if (Wurde die Position rechts davon bereits bearbeitet) {
Rechten Punkt in die QQueue
}
// dito rechts und links...
}
}
... und da heißt es immer, auf die Größe käme es nicht an.Christian81 hat geschrieben:Dein Stack ist einfach zu klein - da gibts nichts zu korrigieren...
Da hab ich wohl Pech.
@upsala:
Das hieße aber - wenn ich das richtig interpretiere - alle Startpositionen bereits in der Queue zu haben. Ich kenne aber zu Beginn keine, sondern diese "ergeben sich im Laufe der Zeit".
Der Pseudocode für das, wozu ich die Funktion verwende, lautet:
Code: Alles auswählen
Füllfarbe = 1; // Nicht schwarz
Durchlaufe das Ausgangsbild // im PGM Format, enthält zu Beginn der Funktion nur schwarze und weiße Pixel
{
Wenn das aktuelle Pixel weiß ist
{
startPosition = aktuellesPixel;
FülleBereich( Ausgangsbild, startPosition, Füllfarbe );
}
Füllfarbe++;
Wenn Füllfarbe = weiß
{
Füllfarbe = 1;
}
}Gruß,
gelignite
{brigens ist ein Kezboard/Treiber v;llig [berfl[ssig!
sei kreativ.. für dein Problem gibt es ne Menge Lösungen (rekursive als auch iterative). Eine häufige iterative Strategie ist (wie upsala mit dem Pseudocode demonstriert), eine "Datenbank" zu halten welche die gleichen Informationen umfasst, welche bei der Rekursion auf dem Stack landen würden (also die neuen Koordinaten).gelignite hat geschrieben: Die iterative Lösung würde mir auch besser gefallen, aber eine iterative Lösung dazu (siehe Code oben) kenne ich nicht.
...
das hieße aber - wenn ich das richtig interpretiere - alle Startpositionen bereits in der Queue zu haben. Ich kenne aber zu Beginn keine, sondern diese "ergeben sich im Laufe der Zeit".
Dein Programm verwendet den zugewiesenen virtuellen Speicher falsch... das passt doch haargenau....gelignite hat geschrieben: Ich hätte dann allerdings etwas Aussagekräftigeres als "Segmenation fault" erwartet.![]()