programm problem mit code
-
du solltest objekt zeiger, für die du lokal in einer funktion speicher über new reservierst, am ende der funktion den speicher wieder frei geben..
die globalen objekte kannst du ja under FormDestroy freigeben.
den zB. in der funktion
void __fastcall TForm1::ListBox1Click(TObject *Sender)
wird mit jedem aufruf speicher für
TControl *my = new TControl(Application);
reserviert.. das frisst langsam mit jedem aufruf deine resourcen und füllt deinen speicher.
irgendwan ist der speicher voll und läuft über
egal, ob das nun der grund ist oder nicht, ohne "delete" ist es nicht sauber programmiert und wird früher oder später nur ärger geben.
einfach am ende der funktiondelete my;hinzufügen
-
gut, mein erster gedanke war es auch, soviele zeiger erstellen und nie freigeben kann nicht gut sein, aber dieses hier kompiliert er nie:
******* quelldatei mit delete ************
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "main.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; bool Start=false; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::ListBox1Click(TObject *Sender) { try{ ListBox2->Items->Clear(); Caption=ListBox1->Items->Strings[ListBox1->ItemIndex] ; TControl *my = new TControl(Application); my = FindChildControl(ListBox1->Items->Strings[ListBox1->ItemIndex]); Shape1->Left = my->Left - 5; Shape1->Top = my->Top - 5; Shape1->Width = my->Width + 10; Shape1->Height = my->Height + 10; Shape1->Visible = true; ListBox2->Items->Add(my->Name); } catch(...) { delete my; my = NULL; } } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { try { TControl *ChildControl = new TControl(Application); for(int i=0; i < this->ComponentCount; i++) { ChildControl = this->Controls[i]; if(ChildControl->Visible) ListBox1->Items->Add(ChildControl->Name); } Shape1->Left=0; Shape1->Top=0; Shape1->Width=0; Shape1->Height=0; Shape1->Visible=true; } catch(...) { delete ChildControl; ChildControl = NULL; } } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { ReleaseCapture(); X=X%5; SendMessage(dynamic_cast <TCheckBox*>(Sender)->Handle,WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { Shape1->Left=X; Shape1->Top=Y; Shape1->Width=0; Shape1->Height=0; Start = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if(Start) { Shape1->Width = X - Shape1->Left; Shape1->Height = Y - Shape1->Top; } } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { try { ListBox2->Items->Clear(); TControl *ChildControl = new TControl(Application); TRect rectc,rects; for(int i=0; i < this->ComponentCount; i++) { ChildControl = this->Controls[i]; if(ChildControl->Name != "Shape1") { rectc = ChildControl->BoundsRect; rects = Shape1->BoundsRect; if (rectc.Left >= rects.Left && rectc.right <= rects.right && rectc.Bottom <= rects.bottom && rectc.top >= rects.top) ListBox2->Items->Add(ChildControl->Name); } } Start=false; Shape1->Left=0; Shape1->Top=0; Shape1->Width=0; Shape1->Height=0; } catch(...) { delete ChildControl; ChildControl = NULL; } } //---------------------------------------------------------------------------gruß gerd
ps:ich bin mir fast sicher dass es daran liegt, dass er abstürze generiert!
-
ok, nehmen wir das beispiel
void __fastcall TForm1::ListBox1Click(TObject *Sender) { try{ ListBox2->Items->Clear(); Caption=ListBox1->Items->Strings[ListBox1->ItemIndex] ; TControl *my = new TControl(Application); my = FindChildControl(ListBox1->Items->Strings[ListBox1->ItemIndex]); Shape1->Left = my->Left - 5; Shape1->Top = my->Top - 5; Shape1->Width = my->Width + 10; Shape1->Height = my->Height + 10; Shape1->Visible = true; ListBox2->Items->Add(my->Name); } catch(...) { delete my; my = NULL; } }meine frage an dich: was bewirkt
try { } catch(...) { }überleg dir auch mal dieses
void __fastcall TForm1::ListBox1Click(TObject *Sender) {// ich reserviere Speicher für my und gebe es am ende der funktion wieder frei TControl *my = new TControl(Application); my->Name = "meinName"; ShowMessage(my->Name); delete my; }[edit] bin dan mal weg... [/edit]
-
hi,
achja, zu meinem oberen code:
er kompiliert es überhaupt nicht, egal ob try-catch konstrukt, oder aussen vor! schonmal probiert?
so nun zu deinem post:
ok, also der try block wird ausgeführt wenn alles fehlerfrei klappt, der catchblock bei einem fehler im tryblock! steht sogar in der hilfe des bcb drin, dass man delete nur in verbindung mit einem try-catch konstrukt nehmen sollte!
beweis:
Objekte, die Sie nicht mehr benötigen, sollten Sie löschen, damit der von diesen Objekten belegte Speicher freigegeben wird. Das Löschen geschieht mit dem Operator delete. (Dieser ruft den Destruktor der Klasse auf, eine Methode, die den für das Objekt reservierten Speicher freigibt.)
Um das nicht mehr benötigte Mitarbeiter-Objekt zu löschen, ist der folgende Aufruf nötig:
delete Mitarbeiter;
Es ist gute Programmierpraxis, den Destruktor im catch-Teil eines try..catch-Blocks aufzurufen. Der Quelltext, in dem das Objekt verwendet wird, sollte sich im try-Abschnitt befinden. Dadurch wird sichergestellt, daß der für das Objekt reservierte Speicher auch dann freigegeben wird, wenn in dem Bereich des Quelltexts, in dem das Objekt verwendet wird, eine Ausnahme auftritt.
doch jetzt das ganz fatale, laut bcb hilfe für den destruktoraufruf des TControl:
Der Destruktor ~TControl gibt eine Instanz von TControl frei.
__fastcall virtual ~TControl(void);
Beschreibung
Rufen Sie ~TControl auf keinen Fall direkt auf. Verwenden Sie statt dessen das Schlüsselwort delete, das mit einer indirekten Referenz auf das Steuerelement arbeitet.
Steuerelement sollten in einer Anwendung nur explizit freigegeben werden, wenn beim Aufruf des Konstruktors kein Eigentümer übergeben wurde.
wichtig dabei der letzte absatz! ich erstelle nur neue objekte durch übergebene owner, also brauche ich es eigentlich nicht löschen!?
und was nun?
achja, nochetwas wichtiges:
TControl *ChildControl = new TControl(Application); for(int i=0; i < this->ComponentCount; i++) { ChildControl = this->Controls[i]; if(ChildControl->Visible) ListBox1->Items->Add(ChildControl->Name); } Shape1->Left=0; Shape1->Top=0; Shape1->Width=0; Shape1->Height=0; Shape1->Visible=true; delete ChildControl;so kompiliert er es zwar, aber meine elemente werden danach gelöscht, wie umgehe ich denn soetwas?
ergänzt: habe jetzt ChildControl und my vorher auf NULL gesetzt, aber immer noch speicherproblem. aber nur bei dieser applikation.
TControl *ChildControl = new TControl(Application); for(int i=0; i < this->ComponentCount; i++) { ChildControl = this->Controls[i]; if(ChildControl->Visible) ListBox1->Items->Add(ChildControl->Name); } Shape1->Left=0; Shape1->Top=0; Shape1->Width=0; Shape1->Height=0; Shape1->Visible=true; ChildControl = NULL; delete ChildControl;gruß gerd
-
Hallo
in dem Fall
ChildControl = NULL; delete ChildControl;einfach weglassen. Das Löschen übernimmt die Application, weil du das mit
new TControl(Application);so zugeordnet hast.
Nur wenn das nicht der Fall ist, must du selber löschen.bis bald
akari
-
gerd01 schrieb:
steht sogar in der hilfe des bcb drin, dass man delete nur in verbindung mit einem try-catch konstrukt nehmen sollte!
Den erste Satz in der Hilfe hast Du dabei aber offenbar überlesen. Wenn Du das so machst, dann wird das Objekt nur
im Falle einer Exception freigegeben. Außerdem wird die Exception unterdrückt - Du merkst außen gar nicht, dass eine
Exception aufgetreten ist. Um sicherzugehen könntest Du anstatt catch __finally verwenden.gerd01 schrieb:
ich erstelle nur neue objekte durch übergebene owner, also brauche ich es eigentlich nicht löschen!?
Sehe ich genauso. Man kann solche Objekte zwar mit delete löschen, aber dann habe ich schon öfters gesehen,
dass die Applikation beim Schließen Exceptions wirft oder ganz hängenbleibt. Bei nicht sichtbaren Komponenente
(z.B. TQuery) kann man einfach als Owner 0 übergeben und dann das Objekt später selbst löschen. Gerade bei
Datenbank-Komponenten bleiben sonst Ressourcen belegt und u.U. sogar irgendwelche Datenbank-Locks.gerd01 schrieb:
und was nun?
Ich möchte die Frage mal umformulieren: Was beabsichtigst Du mit Deinem Code und wieviel davon hast Du selbst
überhaupt verstanden?gerd01 schrieb:
TControl *ChildControl = new TControl(Application); // Wofür wird hier ein neues TControl-Objekt erstellt? Es wird nie angesprochen for(int i=0; i < this->ComponentCount; i++) { // sieht ganz gut aus } // Shape-Gedöns ChildControl = NULL; // Wenn Du diese Zeile (wie in Deiner vorherigen Version) weglässt, was wird dann gelöscht? delete ChildControl; // Was sollte hier gelöscht werden, wenn Du den Zeiger vorher auf NULL (=0) setzt?Gruß,
Alexander
Edit: Gute Überschrift übrigens

-
hallo leute,
@akari:
ja, aber das hatte ich ja am anfang auch gelesen, und deshalb ja eigentlich weg gelassen, wurde jetzt nur drauf hingewiesen, dass man es einbauen sollte, aber warum stürzt mein proggie ab.----------------
@Alexander Kempf:
a)
ich wüsste nicht wo ich ihn überlesen haben sollte, weiter steht da nix, erscheint mir aber eigentlich auch logisch, dass man es nicht im catch machen kann, der wird ja nur aufgerufen, wenn try fehlschlägt.b)
zu den nicht sichtbaren kompos kann ich nix sagen, aber danke für den tipp!
c)
beabsichtigung ist die markierung von formelementen ähnlich der IDE, meine drei Fragen am anfang des threads sollten aufschluss darüber liefern. da ich diese aber nunmal gestellt habe, habe ich mir ne eigene lösung versucht zu stricken, dabei entstand diese prog.TControl *ChildControl = new TControl(Application); // Wofür wird hier ein neues TControl-Objekt erstellt? Es wird nie angesprochenin der for-schleife, damit ich den namen des objektes bekomme.
d)
meinst du das mit der überschrift ironisch?
kann es mal jemand bei sich testen, ob es dabei auch speicherprobs gibt?
das wäre lieb.zudem hatte ich noch zwei weitere fragen, vielleicht kann da auch jemand was zu sagen?
gruß gerd
-
gerd01 schrieb:
a)
ich wüsste nicht wo ich ihn überlesen haben sollte, weiter steht da nixBCB-Hilfe schrieb:
Objekte, die Sie nicht mehr benötigen, sollten Sie löschen, damit der von diesen Objekten belegte Speicher freigegeben wird.
gerd01 schrieb:
TControl *ChildControl = new TControl(Application); // Wofür wird hier ein neues TControl-Objekt erstellt? Es wird nie angesprochenin der for-schleife, damit ich den namen des objektes bekomme.
Die Frage bleibt bestehen. Die Betonung liegt auf "neues".
gerd01 schrieb:
zudem hatte ich noch zwei weitere fragen, vielleicht kann da auch jemand was zu sagen?
Da gibt's ja die alte Faustregel: 1TpT-1TpT
Auf die Schnelle würde ich vorschlagen, im Moment des Mausklicks festzustellen, welches Shape sich unter dem
Mauszeiger befindet. Dann eine Komponente mit Handle (TPanel o.ä.) an diese Stelle schieben und das Shape
darauf anzeigen (Parent auf Panel setzen). Dann kannst Du das Panel mit dem Shape verschieben und beimLoslassen alles wieder umgekehrt machen. Ich habe aber keine Ahnung, ob das so funktioniert.
Gruß,
Alexander
-
Hi,
Eventuell lässt sich das was mit drag & dock machen, was das verschieben der komponenten angeht ... guck dir das doch mal an.
Zitat:
TControl *ChildControl = new TControl(Application); // Wofür wird hier ein neues TControl-Objekt erstellt? Es wird nie angesprochenin der for-schleife, damit ich den namen des objektes bekomme.
if(Controls[i]->Visible) ListBox1->Items->Add(Controls[i]->Name);geht nich ?
-
@Alexander Kempf:
ok, danke erstmal für den trick mit dem panel, damit bekomme ich endlich nen handle!
zu:
Die Frage bleibt bestehen. Die Betonung liegt auf "neues".
anderen vorschlag?
---------------
@prolog:nein, leider geht das bei mir nicht, deshalb der umweg über ein neues objekt!
gruß gerd
-
gerd01 schrieb:
anderen vorschlag?
Was ist das Gegenteil von ein neues Objekt anlegen?
gerd01 schrieb:
nein, leider geht das bei mir nicht, deshalb der umweg über ein neues objekt!
Glaube ich nicht.
Gruß,
Alexander
-
Alexander Kempf schrieb:
gerd01 schrieb:
anderen vorschlag?
Was ist das Gegenteil von ein neues Objekt anlegen?
gerd01 schrieb:
nein, leider geht das bei mir nicht, deshalb der umweg über ein neues objekt!
Glaube ich nicht.
Gruß,
Alexander
nagut, es geht wohl doch, war zu voreilig, nur weil er die programmierhilfe nicht geöffnet hat, ging ich davon aus, es wäre nicht möglich, sorry.
aber immer noch speicherfehler, da das my drin bleibt.
zusatz:
aber testet ihr es auch selber mal, vielleicht ist es ja ein allgemeines problem?
gruß gerd
-
gerd01 schrieb:
aber immer noch speicherfehler, da das my drin bleibt.
Dann nimm's halt raus.
Gruß,
Alexander
-
und wie soll ich das umschreiben:
ListBox2->Items->Clear(); Caption=ListBox1->Items->Strings[ListBox1->ItemIndex] ; TControl *my = new TControl(Application); my = FindChildControl(ListBox1->Items->Strings[ListBox1->ItemIndex]); ListBox2->Items->Add(my->Name); Shape1->Left = my->Left - 5; Shape1->Top = my->Top - 5; Shape1->Width = my->Width + 10; Shape1->Height = my->Height + 10; Shape1->Visible = true;es ist ja auch nur eine vermutung, dass es jetzt vielleicht doch daran liegt!
gruß gerd
-
gerd01 schrieb:
und wie soll ich das umschreiben:
Du willst doch ein bestehendes Control finden? Warum erstellst Du denn dann zunächst eines?
Schreib doch anstatt:TControl *my = new TControl(Application); my = FindChildControl(ListBox1->Items->Strings[ListBox1->ItemIndex]);einfach:
TControl *my = FindChildControl(ListBox1->Items->Strings[ListBox1->ItemIndex]);und lösche my dann auf keinen Fall, sonst löschst Du das gefunden Control und das wäre doch schade.
gerd01 schrieb:
es ist ja auch nur eine vermutung, dass es jetzt vielleicht doch daran liegt!
Dann solltest Du Dir Gewissheit verschaffen.
Gruß,
Alexander
Edit: Du solltest natürlich überprüfen, ob FindChildControl auch was vernünftiges zurückgibt.
-
oha, natürlich, einach den zeiger kopieren!

danke für den atritt
ok, speicherproblem bleibt bestehen, hängt jetzt aber mit grünem pfeil in dieser zeile:
ListBox2->Items->Add(my->Name);jetzt irgendwelche ideen?
gruß gerd
-
Vielleicht ist FindChildControl() nicht das richtige. Versuch's mal mit FindComponent() und (wie vorher im Edit gesagt)
prüfe, ob Du auch einen Wert zurückbekommst. Das könntest Du aber auch im Debugger sehen.Gruß,
Alexander
-
danke, werde es probieren.
zumindest bekomme ich mit findchildcontrol bei den labels nichts zurück!
gruß gerd
-
aber da bekomme ich nicht die positionen heraus, da left und sowas erst ab TControl enthalten sind!
gruß gerd
-
so, habe mal nen neues projekt gestartet, und siehe da, speicherfehler treten nur noch bei den labels auf, da bekomme ich irgendwie keine daten zurück über die findchildcontrol() funktion.
ansonsten läuft es rund
gruß gerd