Stacküberlauf !?!



  • Hallo, erstmal die Frage, wie kann es zu einem Stacküberlauf kommen, und wie kann man diesen beheben.

    Bei mir taucht dieser auf, wenn

    Meine Datenbank leer ist, ich einen neuen Datensatz hinzufüge, und dann ein TADOQuery Schließe, weil es danach neu geöffnet werden soll, damit das DBGrid aktuallisiert wird.

    Nun da dieses nicht klappte, habe ich es so gelöst, das wenn der erste datensatz eingetragen wird, das fenster einmal geschlossen und neu Geöffnet werden muss. Und dann beim öffnen der Form, tritt dieser Stacküberlauf auf. Weis da leider nicht weiter 😞

    Gruß
    Thorsten



  • Lokale Variablen und Rücksprungsadressen werden auf dem Stack platziert. Somit könnte eine Endlosrekursion (zu viele verschachtelte Funktionsaufrufe, sodass die Rücksprungsadressen den Stack gefüllt haben) oder ein zu großes Objekt wie char test[100000000]; einen Stack overflow erzeugen. Poste am besten mal den entsprechenden Teil denes Quelltextes an dem der Fehler auftritt, sonst lässt sich nur schwer erkennen, wo genau der Fehler liegt.



  • ok hier der code

    das passiert wenn die form geöffnet wird

    void __fastcall TForm6::FormActivate(TObject *Sender)
    {
      adoconn_ftp->Connected=true;    //herstellen der Datenbankverbindung
    
      adoqu_alle->Open();  //query mit dem der anweisung zum laden aller bezeichnungen
                           //öffnen
    
      //sollte ein Datensatzvorhanden sein
      if(!(adoqu_alle->RecordCount==0))  //Wenn Anzahl ungleich 0 !
      {
        dbgrid_einst->Enabled = true; //wird das DBGrid aktiviert
      }
      else
      {
        dbgrid_einst->Enabled = false; //ansonsten wird es deaktiviert
      }
    
    }
    

    das passiert wenn ich auf "Speichern" klicke.

    void __fastcall TForm6::cmd_ftpspeichernClick(TObject *Sender)
    {
        //Variablen Deklaration
        int i_port=0;
    
        if(txt_bezeichnung->Text=="")
        {
          MessageDlg("Bitte geben Sie für die neue Einstellung eine Bezeichnung ein!", mtInformation, TMsgDlgButtons() << mbOK, 0);
        }
         else if(txt_host->Text=="")
         {
           MessageDlg("Bitte geben Sie für die neue Einstellung einen Host ein!", mtInformation, TMsgDlgButtons() << mbOK, 0);
         }
          else if(txt_port->Text=="")
          {
            MessageDlg("Bitte geben Sie für die neue Einstellung einen Port ein!", mtInformation, TMsgDlgButtons() << mbOK, 0);
          }
           else if(txt_username->Text=="")
           {
             MessageDlg("Bitte geben Sie für die neue Einstellung einen Usernamen ein!", mtInformation, TMsgDlgButtons() << mbOK, 0);
           }
           else
           {
              try
              {
                  i_port=StrToInt(txt_port->Text); //der var i_port den wert aus der Textbox
                                                   //txt_port zuweisen, als Integer.
                                                   //Damit wird geprüft, ob die Eingabe auch eine
                                                   //Zahl ist!!
    
              }
               catch(...)
               {
                 //Sollte die Eingabe in txt_port keine Zahl sein, wird dieser Block
                 //ausgeführt und gibt eine Fehlermeldung aus
                 MessageDlg("Der Port muss eine Zahl sein!", mtInformation, TMsgDlgButtons() << mbOK, 0);
               }
    
               AnsiString a_port;
               a_port=IntToStr(i_port);
    
               //ausführen wenn a_port nicht leer ist.
               if(!(a_port==""))
               {
                   adoqu_save->SQL->Clear(); //Löschen der SQL Strings
    
                   //Hinzufügen des SQL String
                   adoqu_save->SQL->Add("INSERT INTO tb_ftp (bezeichnung,host,port,username)");
                   adoqu_save->SQL->Add("VALUES ('"+txt_bezeichnung->Text+"','"+txt_host->Text+"','"+a_port+"','"+txt_username->Text+"')");
    
                    adoqu_save->ExecSQL(); //INSERT Befehl ausführen
    
                    try
                    {
                      //##########################################
                      //####    HIER TRITT DER FEHLER AUF ####
                      //####    ABER AUCH NUR WENN DIE DB LEER IST. IST SCHON EIN DATENSATZ DRINN, WIRD NICHT GEMEKERT ####
    
                      adoqu_alle->Close();//query mit dem der anweisung zum laden aller bezeichnungen
                                        //schließen
    
                      //#### HIER TRITT DER FEHLER AUF ENDE
    
                     adoqu_alle->Open();  //query mit dem der anweisung zum laden aller bezeichnungen
                                          //öffnen
                    }
                    catch(...)
                    {
                       if((MessageDlg("Bei dem ersten Eintrag, muss dieses Fenster leider einmal geschlossen \n und wieder neu aufgerufen werden! ", mtConfirmation, TMsgDlgButtons() << mbOK, 0)) == mrOk)
                       {
                         Form6->Close();
                       }
                    }
    
                   //textfelder deaktvieren
                   txt_bezeichnung->Enabled = false;
                   txt_host->Enabled = false;
                   txt_port->Enabled = false;
                   txt_username->Enabled = false;
    
                   //textfelder inhalt löschen
                   txt_bezeichnung->Clear();
                   txt_host->Clear();
                   txt_port->Clear();
                   txt_username->Clear();
    
                   //button freigeben
                   cmd_ftpnew->Enabled = true;
                   cmd_load->Enabled = true;
    
                   //button deaktivieren
                   cmd_reset->Enabled  = false;
                   cmd_ftpspeichern->Enabled = false;
    
                   dbgrid_einst->Enabled = true;
                   dbgrid_einst->Refresh(); //DBGrid aktuallisieren
    
               }
    
           }
    
    }
    

    und das wird dann beim schließen der Form ausgeführt

    void __fastcall TForm6::FormClose(TObject *Sender, TCloseAction &Action)
    {
       adoconn_ftp->Connected = false;   //schließen der Datenbankverbindung
    
       //textfelder inhalt löschen
       txt_bezeichnung->Clear();
       txt_host->Clear();
       txt_port->Clear();
       txt_username->Clear();
    
       //textfelder deaktivieren
       txt_bezeichnung->Enabled = false;
       txt_host->Enabled = false;
       txt_port->Enabled = false;
       txt_username->Enabled = false;
    
       //button deaktivieren
       cmd_reset->Enabled = false;
       cmd_ftpspeichern->Enabled = false;
       cmd_akt->Enabled = false;
       cmd_delete->Enabled = false;
    
       //button aktivieren
       cmd_ftpnew->Enabled = true;
       cmd_load->Enabled = true;
    
       //dbGrid aktivieren
       dbgrid_einst->Enabled = true;
    }
    

    ich hoffe das reicht 😉



  • die fehlermeldung, wenn kein datensatz drinn ist, ist dann halt "Entweder BOF oder EOF wurde erreicht, oder kein Datensatz ..." so in der art.

    muss dann, durch meine hervorgerufene Meldung, das fenster geschlossen und wieder aufgerufen werden, dann kommt der Stacküberlauf



  • Hallo

    hast du für für adoqu_alle irgendwelche Datasources, die in OnDataChange-Events den Status von adoqu_alle verändern, so das der Event (immer) wieder aufgerufen wird?
    Mach an diesem Punkt mal einen Breakpoint, und lauf mit F7 alle nachfolgenden Funktionen ab.
    Auch das Debug-Fenster in Menü Ansicht/Debug-Fenster/Aufruf-Stack kann während der Laufzeit Details zum Aufruf liefern.

    bis bald
    akari



  • Ich habe auf der Form ein DataSource mit DateSet=adoqu_alle.
    In dem Ereignis OnDataChange habe ich keinen Code! Das komische ist ja halt nur, das es nur auftaucht, wenn nuoch kein datensatz vorhanden ist



  • Hi,

    welche DB verwendest Du?

    Ich hab mal irgendwo gelesen, dass TADOQuery unter Umständen Probleme bereitet...
    Versuch doch mal statt TADOQuery ein TADODataSet und für die Speicherung der Daten ein TADOCommand zu verwenden.

    adoqu_save->SQL->Clear(); //Löschen der SQL Strings
    //Hinzufügen des SQL String
    adoqu_save->SQL->Add("INSERT INTO tb_ftp (bezeichnung,host,port,username)");
    adoqu_save->SQL->Add("VALUES ('"+txt_bezeichnung->Text+"','"+txt_host->Text+"','"+a_port+"','"+txt_username->Text+"')");
    

    Dieses Konstrukt will mir auch nicht so richtig gefallen. Sieh Dir mal die Funktion QuotedStr() an. Besser wäre es allerdings mit Parametern zu arbeiten.
    Außerdem würde es die Fehlersuche erleichtern, wenn die cmd_ftpspeichernClick-Funktion in kleinere Teilfunktionen zerlegen würdest.
    Werteüberprüfung, Speichern, Öffnen und Schließen des Datasets würde ich in separaten Funktionen machen.



  • ich benutze eine Access DB.

    das mit den funktionen meinst, das ich z.B. die aktuallisierung in eine funktionschreibe, da ich dieses bei mehreren Klick Ereignisse nutze?

    dann muss ich mir das mit den funktionen nochmal genauer anschauen.



  • hmm kann mir da einer bei den funktionen helfen? weis nicht wie man die deklariert

    habe nur mal was gelesen mit

    void funktion(void);
    ...
    

    dann aufrufen mit

    funtion();
    

    und dann da drunter irgendwo

    void funktion(void)
    {
    
      irgend ein code.
    }
    

    nur half mir das alles irgendwie nicht weiter.
    wenn einer ein tutorial zu funktionen oder website blabla kennt, kann sie mir bitte hier mitteilen. Wäre echt nett.

    Gruß
    Thorsten



  • Hallo

    schau einfach auf diese Seite im Menü oben rechts, da ist ein Eintrag Tutorials.
    Nimm eins aus der C++ Reihe, denn das sind die Grundlagen die du brauchst.

    bis bald
    akari



  • ja, mein problem ist halt nur, das da immer steht

    funktione ...

    int main()
    {
    programmcode
    }

    int funktione()
    {

    }

    usw.

    und nicht was mit

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
    
    }
    //---------------------------------------------------------------------------
    
    Wohin mit der funktions deklaration?
    Wohin mit dem funktions programm ablauf {} usw.
    

    da ist mein problem das mit dem cout<< habe ich so in c++ noch nie gemacht etc. nur in c dann aber auch mit printf und so

    ich bräuchte praktisch zu dem c++ code da oben nur ein Beispiel, wo was hinkommt!?! dann würde ich das wohl raffen.



  • Hallo

    wenn du direkt etwas mit

    int main()
    {
    programmcode
    }
    

    siehst, ist es ein Konsolenprogramm. Soetwas erstellst du mit dem Konsolenexperten. (Menü Datei/Neu.../Konsolen-Experte).

    Eine Standard (VCL-) Anwendung ist bereits voll in einer OOP-Struktur integriert, sodas die Funktionen, die du siehst, Methoden von TForm1 sind.

    Wenn du eine neue Funktion in einer VCL-Anwendung erstellen willst, must du also erstmal entscheiden, ob du eine unabhängige Funktion erstellen willst : dann einfach in der Implementationsdatei schreiben, und wenn nötig in der Headerdatei deklarieren.

    Methoden für Form1 erstellst du lieber erstmal mit dem Objektinspektor.

    Wie ich schon schrieb, solltest du dein Grundwissen durch Tutorials aufbauen, denn dort wird das alles (und mehr) erklärt.

    bis bald
    akari



  • meinst du am objektinspokter die ereignisse ??



  • Hallo

    ja, das habe ich damit

    Methoden für Form1 erstellst du lieber erstmal mit dem Objektinspektor.

    gemeint.
    Ereignisse sind BCB-spezifische Anwendungen von Funktionspointern auf Klassenmethoden. Im OI kann man diese einfach erstellen, zuweisen und löschen.
    Was aber auch per Code zur Laufzeit geht.

    bis bald
    akari



  • ahso, ich glaube da reden wir grade an einander vorbei. wie man so ereignisse erstellt ist klar, ichmeinte, das ich einefunktion schreibe, die öfters im code aufgerufen wird sprich:

    beispiel(ist nict richtig)

    int funktion(void);

    hauptteil(void)
    {
    hier steht ein text drinnen oder das Klickereigniss wird ausgelöst

    funktion();

    weiter im kot

    }

    funktion(void)
    {
    txt1->Enabled=true;
    ...

    }

    usw.



  • Hallo

    dir fällt es einfacher, ein Ereigniss zu erstellen als eine einfache Funktion? Da sieht man mal, was fehlendes Grundwissen ausmacht.

    Im Grunde ist das ganz einfach

    // Implementation einer Funktion
    int Func1(int Value)
    {
      return(Value *2);
      }
    
    void __fastcall TForm1::OnClick(TObject *Sender)
    {
      int Value = StrToIntDef(Edit1->Text, 0);
      Label1->Caption = IntToStr(Func1(Value)); // Funktion wird angewendet
    }
    //---------------------------------------------------------------------------
    

    Solche Funktionen sind dann natürlich nicht im Kontext von Form1. Wenn du die Eigenschaften von TForm1 benutzten willst, must du noch diese Funktion als Methode von TForm1 deklarieren.
    [cpp]// In Headerdatei :
    __private :
    ...
    int Func1(int Value); // Deklaration hinzufügen
    __public :

    int **TForm1::**Func1(int Value)
    {
    if (CheckBox1->Checked) return(Value *2);
    return(Value / 2);
    }

    void __fastcall TForm1::OnClick(TObject *Sender)
    {
    int Value = StrToIntDef(Edit1->Text, 0);
    Label1->Caption = IntToStr(Func1(Value)); // Funktion wird angewendet
    }
    //---------------------------------------------------------------------------
    [/cpp]btw : bitte benutzt im Forum die Code-Tags (Wenn du einen Post schreibst, Code-Text markieren und den C++ Knopf unter den Smilies drücken)



  • ok, das werde ich mir dann morgen nochmal genau anschauen. genau sowas habe ich gesucht. wusste garnicght, dass das klickereigniss auch in dem header geschrieben werden muss ??

    ja und zu der einfachheit des ereignisses, da braucht man doch im OI doch nur zweimal draufklicken, dann wird der code erzeugt und man fügt seinen dazwischen einfach ein ??

    danke aufjedenfall

    gruß
    thorsten



  • ThorstenSteinberg schrieb:

    wusste garnicght, dass das klickereigniss auch in dem header geschrieben werden muss ??

    ja und zu der einfachheit des ereignisses, da braucht man doch im OI doch nur zweimal draufklicken, dann wird der code erzeugt und man fügt seinen dazwischen einfach ein ??

    genau das ist der Punkt. Der OI macht beim Doppelklick auf ein Eventfeld genau diese Änderungen : Er trägt die Deklaration der Methode in die Headerdatei und den Methodenrumpf in die Implementationsdatei.
    Das ist natürlich bequem, verbirgt aber die eigentliche Struktur dahinter.

    bis bald
    akari



  • ahhhh ok danke, werde ich mir morgen aufjedenfall einmal anschauen



  • hmm, wie du siehst, habe ich ja viel ereignisse in der form 6, (quellcode auf seite 1) in der header datei steht aber kein weiteres ereignis nur folgendes:

    //---------------------------------------------------------------------------
    
    #ifndef mymp3s_u6H
    #define mymp3s_u6H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ADODB.hpp>
    #include <Db.hpp>
    #include <DBTables.hpp>
    #include <Buttons.hpp>
    #include <DBCtrls.hpp>
    #include <DBGrids.hpp>
    #include <Grids.hpp>
    #include <Mask.hpp>
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm6 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
            TGroupBox *grp_newverbindung;
            TButton *cmd_ftpspeichern;
            TButton *cmd_akt;
            TButton *cmd_ftpnew;
            TADOConnection *adoconn_ftp;
            TGroupBox *GroupBox1;
            TButton *cmd_delete;
            TButton *cmd_load;
            TBitBtn *bcmd_help;
            TDataSource *DataSource1;
            TPanel *Panel1;
            TLabel *lbl_username;
            TLabel *lbl_host;
            TLabel *lbl_port;
            TLabel *lbl_bezeichnung;
            TADOQuery *adoqu_alle;
            TDBGrid *dbgrid_einst;
            TDBEdit *dbtxt_id;
            TEdit *txt_bezeichnung;
            TEdit *txt_host;
            TEdit *txt_port;
            TEdit *txt_username;
            TButton *cmd_reset;
            TADOQuery *adoqu_load;
            TADOQuery *adoqu_save;
            TADOQuery *adoqu_delete;
            void __fastcall FormActivate(TObject *Sender);
            void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
            void __fastcall bcmd_helpClick(TObject *Sender);
            void __fastcall cmd_ftpnewClick(TObject *Sender);
            void __fastcall cmd_resetClick(TObject *Sender);
            void __fastcall cmd_loadClick(TObject *Sender);
            void __fastcall dbgrid_einstCellClick(TColumn *Column);
            void __fastcall cmd_aktClick(TObject *Sender);
            void __fastcall cmd_ftpspeichernClick(TObject *Sender);
            void __fastcall cmd_deleteClick(TObject *Sender);
    private:	// Anwender-Deklarationen
    public:		// Anwender-Deklarationen
            __fastcall TForm6(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm6 *Form6;
    //---------------------------------------------------------------------------
    #endif
    

    naja,. jetzt geh ich aber off, bin voll fertig.

    bis dann thx
    thorsten


Anmelden zum Antworten