Variablen in anderen Modulen nicht sichtbar ?!?



  • Hallo,
    Ich habe eine verkettete Liste. Die Elemente werden dynamisch beim Click eines Buttons gefüllt.
    In dieser Funktion (ButtonClick) sind die Elemente gefüllt.
    Will ich über einen anderen Button darauf zugreifen, also einen neue Funktion, bekomm ich eine Speicherzugriffsverletzung...

    Kann ich vielleicht die "sichtbarkeit" der Pointer vergrößern ???



  • an andrer stelle deklarieren ?



  • Moin!

    Eigentlich sollte das kein problem sein. Poste doch mal ein bischen Code dann können wir vielleicht mehr sagen.



  • Header Unit1:

    //---------------------------------------------------------------------------
    
    #ifndef Terminplaner_U_1H
    #define Terminplaner_U_1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    //---------------------------------------------------------------------------
    class THaupt : public TForm
    {
    __published:    // Von der IDE verwaltete Komponenten
        TButton *btnNeuTermin;
        TButton *btnTermineAn;
        void __fastcall btnNeuTerminClick(TObject *Sender);
        void __fastcall btnTermineAnClick(TObject *Sender);
    private:    // Anwender-Deklarationen
    public:     // Anwender-Deklarationen
        __fastcall THaupt(TComponent* Owner);
    };
    
     struct T_Termin {
        AnsiString KBez;
        AnsiString Bez;
        AnsiString Dat;
        AnsiString Uhr;
        T_Termin *Next;
    };
    
    static T_Termin *Anfang;
    static T_Termin *Termine;
    static bool FirstElement = true;
    static int iAnzahlEl = 0;
    
    //---------------------------------------------------------------------------
    extern PACKAGE THaupt *Haupt;
    //---------------------------------------------------------------------------
    #endif
    

    Unit1:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Terminplaner_U_1.h"
    #include "Terminplaner_U_2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    THaupt *Haupt;
    //---------------------------------------------------------------------------
    __fastcall THaupt::THaupt(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall THaupt::btnNeuTerminClick(TObject *Sender)
    {
        NeuTermin->Show();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall THaupt::btnTermineAnClick(TObject *Sender)
    {
            Termine = Anfang;
        for (int x = 0; x <= iAnzahlEl; x++){
            ShowMessage(Termine->KBez);
            Termine = Termine->Next;
        }
    }
    //---------------------------------------------------------------------------
    

    Unit2:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Terminplaner_U_1.h"
    #include "Terminplaner_U_2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TNeuTermin *NeuTermin;
    //---------------------------------------------------------------------------
    __fastcall TNeuTermin::TNeuTermin(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TNeuTermin::btnNeuAbbrechenClick(TObject *Sender)
    {
        NeuTermin->Close();  
    }
    //---------------------------------------------------------------------------
    void __fastcall TNeuTermin::btnNeuSpeichernClick(TObject *Sender)
    {
        if (FirstElement == true){
            FirstElement = false;
            Anfang = new T_Termin;
        Termine = Anfang;
            Termine->KBez = edtNeuKBez->Text;
            Termine->Bez = edtNeuBez->Text;
            Termine->Dat = edtNeuDat->Text;
            Termine->Uhr = edtNeuUhr->Text;
            iAnzahlEl++;
        }
        else{
        Termine->Next = new T_Termin;
            Termine = Termine->Next;
            Termine->KBez = edtNeuKBez->Text;
            Termine->Bez = edtNeuBez->Text;
            Termine->Dat = edtNeuDat->Text;
            Termine->Uhr = edtNeuUhr->Text;
            iAnzahlEl++;
        }
        NeuTermin->Close();
    }
    //---------------------------------------------------------------------------
    


  • hmmm das is doch prima so `??



  • Hmm

    Hast du dir das ganze schon im debugger angesehn, evtl passt ja vorher schon was nicht?? 😕 An welcher Zeile kommt denn die verletztung?

    Denn ich kann mich 1ntrud0r nur anschließen.



  • Ein paar Fragen:

    1. Wieso globale Variablen?
    2. Wieso static-Variablen?
    3. Wie stellst du das Ende deiner Liste fest? (Wenn ich das richtig sehe wird bei einem Angefügten Element "Next" gar nicht initialisiert?
    4. Wäre es nicht eleganter Next auf NULL zu initialisieren und dies als zusätzliche Abbruchbedingung für Schleifen etc. zu verwenden? (Laufzeitsicherheit ist erheblich höher als mit einer separaten Zählvariable)

    -junix



  • @ Puppetmaster 2k : Stelle an der der Fehler auftritt ist rot fett hervorgehoben...
    Nein ich habe es mir noch nicht im Debugger angeschaut. Dafür kenn ich mich zuwenig mit dem Teil aus. Wo kann ich was über den Debugger nachlesen außer in der Hilfe ???

    @ junix: 1.Wieso globale Variablen? - Weil ich möchte dass die Struktur überall sichtbar ist, dass ich auf sie Zugreifen kann.
    2. Die static-Varibalen brauch ich weil ich sonst eine Linker-Warnung bekomme dass die Variablen doppelt deklariert bzw. definiert wurden. Weil ich beide Header-Dateien in beiden Modulen einbinden muss.
    3. Das Ende der Liste stell ich durch diesen Zähler fest. Ja ich könnte den Next-Wert (Anfang der Liste) auf NULL setzen. Gute idee. Dann brauch ich aber immernoch einen Zähler, damit ich weiß wie lang meine Liste ist.
    4. siehe 3.

    [cpp]//--in Unit1:
    void __fastcall THaupt::btnTermineAnClick(TObject *Sender)
    {
    Termine = Anfang;
    for (int x = 0; x <= iAnzahlEl; x++){
    ShowMessage(Termine->KBez);
    Termine = Termine->Next;
    }
    }[/cpp]

    <edit>Bitte in Zukunft C++-Code-Tags verwenden und Quellcode-Listings auf das nötige beschränken. Danke.</edit>

    [ Dieser Beitrag wurde am 06.06.2003 um 14:25 Uhr von junix editiert. ]



  • 1. Globale Variablen sind grundsätzlich zu vermeiden. Hier jetzt aber nicht so schlimm (hättest die Terminliste z.B. in dein Hauptform integrieren können)

    2. Das Problem löst man nicht mit satic sondern mit einer neudeklaration mit vorangestelltem "extern".

    3. Gut, den Zähler brauchst du noch dafür, aber du kannst, wenn du in Schleifen NULL als Enderkennung benutzt nichtmehr die anzahl der Elemente, weshalb du dann auch nichtmehr ungültige Zugriffe (über die Liste hinaus) machen kannst wie dus jetzt grad tust.

    Zum Thema Debuggen steht in der FAQ was nettes bzw. Da wird auf ein Tutorial verwiesen. Schau dich da mal um.
    Ich hab den Fehler glaub ich gesehen, lass dich aber lieber mit dem Debugger arbeiten, denn Übung macht den Meister.

    Tip: Der Fehler liegt ganz klar in der for-Schleife die du oben gepostet hast.

    -junix

    [ Dieser Beitrag wurde am 06.06.2003 um 14:27 Uhr von junix editiert. ]



  • Original erstellt von Diehler:
    [QB@ junix: 1.Wieso globale Variablen? - Weil ich möchte dass die Struktur überall sichtbar ist, dass ich auf sie Zugreifen kann.
    2. Die static-Varibalen brauch ich weil ich sonst eine Linker-Warnung bekomme dass die Variablen doppelt deklariert bzw. definiert wurden. Weil ich beide Header-Dateien in beiden Modulen einbinden muss.
    3. Das Ende der Liste stell ich durch diesen Zähler fest. Ja ich könnte den Next-Wert (Anfang der Liste) auf NULL setzen. Gute idee. Dann brauch ich aber immernoch einen Zähler, damit ich weiß wie lang meine Liste ist.
    4. siehe 3.
    [/QB]

    normalerweise stellen einzelne units nur globale funktionen bereit ... wenn überhaupt. ( um Werte und Variablen zurückzugeben ). Variablen sind im Normalfall private oder protected anzusiedeln.

    2. Normalerweise machen das die PreProcessor Direktiven für dich post mal die 2 Header datei ich glaub du hast mist gebaut nicht die ide.



  • Original erstellt von 1ntrud0r:
    2. Normalerweise machen das die PreProcessor Direktiven für dich post mal die 2 Header datei ich glaub du hast mist gebaut nicht die ide.

    Nur gehts hier darum, dass in zwei Object-Files die selbe globale Variable deklariert wurde. Der Linker warnt davor, dass der Selbe bezeichner verwendet wurde und daher nicht 2 mal sondern nur 1 mal Speicher reserviert wurde, was dazu führt, dass die beiden Deklarationen nichtmehr unabhängig sind (wa sbei globalen variablen ja durchaus erwünscht ist, nicht aber bei "Unit-Globalen"-Variablen.

    daher Teilt man dem Compiler schon mit, dass er bei einer neu deklaration der globalen nicht extra speicher zu reservieren braucht, sondern, dass der Speicher bereits in einem "extern"en Obj-File reserviert wurde. (o; Somit bleibt dann im Obj-File ein einzelner Bezeichner übrig.

    -junix



  • //---------------------------------------------------------------------------
    
    #ifndef MitMachAktion_TdoT_U2H
    #define MitMachAktion_TdoT_U2H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm2 : public TForm
    {
    __published:    // Von der IDE verwaltete Komponenten
        TButton *Button1;
        TLabel *lblRF2;
        TLabel *lblRF1;
        TRadioGroup *rbgFR;
        TLabel *lblRFNr;
        void __fastcall Button1Click(TObject *Sender);
    private:    // Anwender-Deklarationen
    public:     // Anwender-Deklarationen
        __fastcall TForm2(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm2 *Form2;
    //---------------------------------------------------------------------------
    #endif
    


  • Junix du brauchst mir das nicht zu erklären.

    die selbe Globale Variable 2mal zu deklarieren ist Verwerflich und fordert die Todesstrafe ... 🙂 auf sowas geh ich nicht näher ein !



  • @Diehler: und gleich nochmal in die FAQ und den Teil über Public/Published-Variablen lesen.

    Ausserdem: Was willst du uns mit dem Listing sagen?

    -junix



  • Original erstellt von 1ntrud0r:
    Junix du brauchst mir das nicht zu erklären.

    War auch weniger für dich als für ihn (o;

    -junix



  • Hallo... ich habe nichts zweimal deklariert bzw. definiert...

    was wollt ihr überhaupt jetzt von mir.

    Ich sollte die zweite Header-Datei rein posten das hab ich gemacht....



  • Original erstellt von Diehler:
    ich habe nichts zweimal deklariert bzw. definiert...

    Doch hast du. Und zwar implizit dadurch, dass du die globalen im 1. header deklariert hast und diesen im zweiten unit auch eingebunden hast. Bedenke: #include veranlasst den Präprozessor zu nichts weiter, als dass dieser das zu includierende File nimmt und die Zeile "#include <bla.h>" durch den Inhalt der Datei ersetzt.

    Original erstellt von Diehler:
    was wollt ihr überhaupt jetzt von mir.

    a) Das du den Hinweisen von mir bezüglich Debuggen nachgehst
    b) Das du die globalen nicht im Header sondern im Implementations-File deklarierst und in allen ausser dem Hauptfile auch als extern deklariest.
    c) Das du die globalen _nicht_ als Static deklarierst (ist übrigens die Lösung für das Problem wieso du aus unit2 nicht die gleichen Werte in der Variable hast wie in unit1 und wenn ich mirs recht überlege, dann dürfte wohl das der Grund für die AccessVoilation sein... Siehe auch meine Hinweise bezüglich "extern" static macht genau das Gegenteil)
    d) Feedback
    e) Würde ich mir wünschen, dass du dich etwas mehr über die Schlüsselwörter informierst die du einsetzt und nicht einfach mal "static" vor ne Variable setzt weil der Linker ne Warnung bringt. Nur weil der nacher schweigt ist das noch lange nicht korrekt.

    -junix

    [ Dieser Beitrag wurde am 06.06.2003 um 15:23 Uhr von junix editiert. ]


Anmelden zum Antworten