Stackoverflow



  • Bei folgenden Prozeduren kommt ein Stackoverflow:

    void TMainForm::parsetreenode( PVirtualNode node, TjanXMLNode2 *dnode )
    {
        TjanXMLNode2 *dn2;
        AnsiString sText;
        if( dnode->nodes->Count != 0 )
        for( int i = 0; i < dnode->nodes->Count; i++ )
        {
            dn2 = ( TjanXMLNode2* )dnode->nodes->Items[ i ];
            sText = dn2->name;
            PVirtualNode Node = MainForm->TreeView->AddChild( node, NULL );
            parsetreenode( Node, dn2 );
        }
    }
    //-------------
    
    void TMainForm::parsetree( )
    {
        TjanXMLNode2 *dn = dom;
        sText = dn->name;
        PVirtualNode Node = MainForm->TreeView->AddChild( MainForm->TreeView->RootNode->FirstChild, NULL );
        parsetreenode( Node, dn );
    }
    //-------------
    

    Es wird die Funktion parsetree() aufgerufen, die wiederum parsetreenode aufruft... innerhalb dieser gibt es eine Rekursion. Der Code baut einen Baum auf, doch anscheinend ist ihm das zuviel. Die Datenstrukturen sind teilweise von anderen Komponenten, was hier aber egal ist. Irgendwie muss das Problem also mit der Rekursion zusammehnängen, das das der exe einfach zuviel wird! Was nun?



  • Klar, was da falsch ist: Du gehst bei Deinem Source davon aus, aus, daß "i" bei einem rekursiven Aufruf bekannt ist. Ist er aber nicht. Der wird wieder auf NULL gesetzt und die Methode ruft sich wieder auf. Dann ist i wieder NULL und ruft sich wieder auf etc....

    dn2 hat immer denselben Wert und deswegen klappt das so nicht.



  • wie geht es denn dann? was muss ich ändern?



  • hab zwar nicht genauer nachgelesen aber eine static-variabel dürfte zimlich sicher helfen. Sauberer wäre es, den i-wert (der ja bestimmt etwas repräsentiert) der aufgerufenen Funktion zu übergeben.

    -junix



  • naja, i spielt insofern eine rolle, dass dn2 dadurch beeinflusst wird (siehe erste zeile der schleife)... wo meinst du, ist das static passend? Irgendwie komm ich jetzt nämlich immer noch nicht weiter.



  • Schon mal selber mit dem Debugger durch dein Schleifenkonstrukt gesteppt? Macht es denn weirklich was du erwartetst?

    -junix



  • Vielleicht würde es auch helfen, wenn Du einfach schreibst, was Du erreichen willst. Liegt vielleicht auch daran, daß ich das Objekt TjanXMLNode2 nicht kenne. Ist das ein Objekt, welches auf weitere Objekte des gleichen Typs verweisen kann? (hab den BCB4 Standard ohne das INet-Geraffel)

    Übrigens frage ich mich, welche Einstellung Du in einem Compiler hast, wenn Du zwei Variablen verwendest, die gleich sind, aber einmal Groß und einmal Kleingeschrieben sind (node und Node). Das is extrem schlechter Programmierstiel und bringt einen in teufels Küche.

    Auch die Variable sText ist hier vollkommen unnötig. Da sollte der Compiler eigentlich auch ne Warnmeldung ausstoßen (Zuweisung eines Werts, der nie verwendet wird).

    Auch die if-Anweisung ist falsch plaziert, weil for() diese Bedinung bereits automatisch abprüft. Ich würde das if() vor dem rekursiven paretreenode setzen.

    Bist denn mal mit dem Debugger durchgegangen und hast geprüft, ob der die richtigen Listen verwendet?



  • Ok, ich finde i. O., dass ihr nachfragt und an meinem Code zweifelt. Nur so kann das Problem gelöst werden. Aber hier habe ich jetzt mal den original richtig funtkionierenden Delphi-Code, der quasi in einem TreeView einem Baum korrekt (!) aufbaut, wohingegen mein Code ein Stackoverflow abwirft (Achja, ich benutze einen anderen Baum, daher die etwas verschiedenen Funktionsaufrfe und Datentypen, aber daran liegt es nicht):

    procedure TForm1.parsetreenode(node:TTreeNode;dnode:TjanXMLNode2);
    var
      n,n2:TTreenode;
      dn,dn2:TjanXMLNode2;
      i,c:integer;
      nodename:string;
    begin
      c:=dnode.nodes.Count;
      if c=0 then exit;
      for i:=0 to c-1 do begin
        dn2:=TjanXMLNode2(dnode.Nodes[i]);
        nodename:=dn2.name;
        n2:=tree.items.AddChild(node,nodename);
        n2.data:=dn2;
        parsetreenode(n2,dn2);
      end;
    end;
    
    procedure TForm1.parsetree;
    var
      n,n2:TTreeNode;
      dn,dn2:TjanXMLNode2;
      nodename:string;
    begin
      dn:=dom;
      nodename:=dn.name;
      n:=tree.Items.AddObject(nil,nodename,dn);
      parsetreenode(n,dn);
    end;
    

    Ich sehe nicht, was ich falsch übersetzt haben könnte.

    **<edit>**Bitte beachte dass es auch den

    tag gibt, der dafür sorgt, dass die Leerschläge erhalten bleiben.</edit>

    [ Dieser Beitrag wurde am 26.01.2003 um 13:10 Uhr von junix editiert. ]



  • Sorry, bei Delphi muß ich passen. Mir fällt aber auf, daß Du bei Delphi mit dem Namen was anderes machst als in Deiner C++ "Übersetzung" und da ich auch die Objekte nicht kenne, muß hier jemand intelligenteres ran...



  • Wenn ich mir das Alles so anschaue muss ich sagen... deine Übersetzung ist schrott. Wo zum Beispiel hast du das "exit" übersetzt?
    Die Zuweisung von dn2 ist völliger unfug schau nochmal in den Delphi-Source.

    Überarbeite deine Übersetzung am besten einfahc mal.

    -junix


Anmelden zum Antworten