Zugriffsverletzung bei Zugriff auf Komponenten eines MDI-Child



  • Hallo Zusammen,
    ich habe hier eine MDI Anwendung mit einem MDI-Child. Das MDI-Child heißt lagerplatz_anlegen. Auf dem Child befindet sich ein DBGrid. Wenn ich einen Button getätige soll folgendes ausgeführt werden:

    lagerplatz_anlegen->DBGrid1->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    

    Leider kommt dann ein Zugriffsfehler. So

    DBGrid1->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    

    würde es funktionieren.

    Ich möchte es aber so haben, wie im ersten Beispiel, da ich das ganze als Funktion auslagern möchte.
    Ich habe schonmal eine andere Andwenung erstellt, da hat es funktioniert. Allerdings war es kein MDI Programm. Muß ich das bei einem MDI-Child anders ansprechen?

    Kann mir jemand sagen, was ich da falsch mache?

    Danke im voraus.
    EPMS



  • Hallo

    Debugger benutzen und mit Breakpoint auf die Stelle die einzelnen Adressen überprüfen. Mehr können wir so dazu nicht sagen.

    bis bald
    akari



  • @akari
    wie überprüfe ich denn die einzelnen Adressen?

    Müsste der Aufruf denn so klappen oder ist da was falsch?

    Der Debugger bricht bei genau der Zeite ab. Dort scheint der Fehler zu liegen.



  • Du überprüfst die Adressen indem du sie dir anzeigen läßt. Eine weiter Möglichkeit wäre: Klick mit der rechten Maustaste auf die Variable (z.Bsp. lagerplatz_anlegen) dann im Kontextmenü auf Fehlersuche/untersuchen gehen.



  • Ich habe jetzt mal was geändert. Über einen neuen Button gebe ich folgends aus:

    anzahlchilds->Caption = MDIChildCount;
    

    Müsste da dann nicht bei einem geöffnetet Child "1" raus kommen?
    Es steht bei mir nur "0".

    Könnte es daran liegen? Das er das Child garnicht richtig erkennt.



  • Hallo

    siehe hier Abschnitt Variablen überwachen. Du kannst u.a. die ganzen einzelnen Ebenen von lagerplatz_anlegen über lagerplatz_anlegen->DBGrid1 usw. nacheinander überprüfen, um die Stelle mit der ungültigen Adresse (meistens ein 0-Zeiger) zu finden.

    De Aufruf selber scheint in Ordnung, ist aber schwer ohne weiteren Code zu beurteilen.

    bis bald
    akari



  • Also, wenn ich mit dem Mauszeiger über lagerplatz_anlegen gehe steht da

    lagerplatz_anlegen=NULL
    

    Bei DBGrid1 steht

    lagerplatz_anlegen->DBGrid1=????
    

    Wäre das schon der Fehler?

    Edit1:

    Für mich sieht das so aus, als wenn er das Fenster nicht erkennt. Als wenn es gar nicht da ist, oder nicht geöffnet ist. Das ist ja das, was ich etwas weiter oben shcon geschrieben habe. Ob bei ChildCount nicht zumindest 1 stehen müsste.



  • Das wäre ein Fehler. NULL ist ein ungültiger Pointer. Nun mußt du halt mal nachschauen warum das so ist. Wo soll lagerplatz_anlegen belegt werden? Funktioniert das?



  • Also im MainForm habe ich ein TMainMenu. Dort rufe ich lagerplatz_anlegen folgendermaßen auf:

    void __fastcall Thauptmenu::Lagerplatzanlegen1Click(TObject *Sender)
    {
        bool gefunden=false;
    
        //Überprüfen ob das MDIChild besteht
        for (int i = MDIChildCount - 1; i >= 0; i--) {
            if ((AnsiString)MDIChildren[i]->ClassName() == "Tlagerplatz_anlegen") {
                MDIChildren[i]->Show();
                gefunden=true;
            }
        }
    
        if (!gefunden) {//Fuhrpark erstellen
            Tlagerplatz_anlegen *lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
            lagerplatz_anlegen->Show();
        }
    }
    

    Dann öffnet sich das Form. Da habe ich noch drei Edit Felder drauf. Dort kann ich auch was eingeben. Und die eingegebenen Daten speichere ich per Button in einer MySQL Datenbank.
    Das funktioniert auch alles wunderbar.

    Verstehe deshalb auch nicht, wieso er das Formular anscheind nicht hat.



  • Hallo

    In Thauptmenu::Lagerplatzanlegen1Click ist *Tlagerplatz_anlegen lagerplatz_anlegen eine lokale Variable.

    Wo immer du lagerplatz_anlegen->.. aufrufst, must du noch sicherstellen, das dort auch die Adresse der erstellten Form ist. Tip : Mach lagerplatz_anlegen zu einer Member-Variablen der Form.

    bis bald
    akari



  • Also meinem Verständnis nach rufe ich lagerplatz_anlegen genau an der Stelle auf die ich oben schon reinkopiert habe. Das ganze steht im MainForm meines Programms.

    Was genau sind denn Member-Variablen und wo geschweige denn wie erstelle ich die in meinem Fall?



  • Membervariablen, sind Variablen innerhalb deiner Form-Klasse. Schau doch mal in die Headerdatei, wo Thauptmenu deklariert wurde. Alle Variablen, die da unter private: public: etc. stehen sind Membervariablen bzw. Funktionen.
    Deine Variable lagerplatz_anlegen ist lokal in Lagerplatzanlegen1Click und somit nach Verlassen dieser Funktion ungültig.
    Schreibs mal so

    if (!gefunden) 
    {
    //Fuhrpark erstellen
       lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
       lagerplatz_anlegen->Show();
    }
    

    PS.
    Es wäre gut, wenn du dir mal ein Grundlagentutorial zu C++ durchliest. Insbesondere alles über Gültigkeitsbereiche von Variablen und Klassen.
    http://tutorial.schornboeck.net/scope.htm
    http://tutorial.schornboeck.net/oop2.htm und nachfolgende Seiten
    Am besten überhaupt alles. 🙂



  • @Braunstein
    So funktioniert das jetzt.

    Was genau ist denn jetzt der Unterschied zwischen:

    Tlagerplatz_anlegen *lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
    

    und

    lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
    

    Im oberen wird lagerplatz_anlegen direkt in der Funktion deklariert. Wo wird es jetzt aber beim unteren deklariert?

    Edit1:
    Danke, werde mir die Links mal anschauen.



  • EPMS schrieb:

    ... Wo wird es jetzt aber beim unteren deklariert?

    In der Headerdatei von Thauptmenu.



  • Hallo

    das untere funktioniert nur wenn bereits eine solche Variable vorher deklariert wurde. Das kann in der selben Methode sein, das kann aber auch als Member der Form oder gar global sein.
    Schau dir noch mal in einem C++Grundlagen-Tutorial Gültigskeitsbereiche/Scopes an.

    bis bald
    akari



  • Werde mir das mal durchlesen.

    Allerdings finde ich in der Headerdatei von Thauptmenu nichts bezüglich "lagerplatz_anlegen". Dort steht darüber nichts.



  • Hallo

    du must doch wissen, wo du die Variable deklariert hast... Tip : benutz die IDE-Funktion zum Suchen von Text in den Projektdateien, um das zu finden.

    bis bald
    akari



  • Andere Variante
    Halte Strg fest und klicke mit der linken Maustaste auf deine Variable in der Funktion, dann springt er zur Deklaration (dauert manchmal etwas).



  • Jetzt habe ich es gefunden. Sie werden in der Headerdatei des jeweiligen Forms deklariert.

    Jetzt habe ich noch eine Frage:
    - Wenn ich im OnCreate oder OnActivate folgendes eingebe:

    lagerplatz_anlegen->Label15->Caption = "test";
    

    Bekomme ich auch wieder eine Zugriffsverletzung. Das liegt doch dann bestimmt auch wieder daran, dass lagerplatz_anlegen noch nicht deklariert ist oder?

    Edit1:
    Wenn ich unter Projekt->Optionen das Formular auf "Automatisch erzeugen" stelle habe ich die Zugriffsverletzung nicht. D.h. wenn ich es nicht automatisch erzeugen lasse ist es noch nicht da und deshalb kommt die Fehlermeldung oder?

    Sorry wegen der vielen Fragen.



  • Die Variable ist schon deklariert. Das ist allerdings nur ein (in OnCreate ungültiger) Zeiger auf Tlagerplatz_anlegen. Erst durch aufrufen von new usw. erzeugst du eine gültige Instanz. Das gleiche geschieht automatisch wenn du das Formular in "Automatisch erzeugen" einträgst.


Anmelden zum Antworten