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östfunktion();
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