Probleme mit Zuweisung von Objektadresse an Pointer



  • Hallo,

    bin neu hier und hoffe, daß ich hier richtig bin mit meiner Frage. Hab mir heute trotz Wälzen zweier C++ -Bücher an folgendem Problem die Zähne ausgebissen und hoffe, daß mir hier jemand weiterhelfen kann. Und zwar funktioniert offenbar die Übergabe der Adresse eines Objekts an einen Pointer nicht richtig, ich bekomme jedenfalls immer eine Fehlermeldung (Zugriffsverletzung).

    Hier die wesentlichen Ausschnitte vom Code (das Fettgedruckte sind 2 Befehle, von denen ich nur einen gleichzeitig ausprobiert habe):

    //---------------Datei Start.cpp--------------------------------------
    
    #include "Start.h"
    #include "controller.h"
    #include "globalVariables.h"
    
    TForm1 *Form1;
    Controller controller;
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
         [b]contr_ptr=&controller;[/b]
         controller.start(*this);
    }
    
    //------------------------ Datei controller.cpp---------------------------------
    
    #include "globalVariables.h"
    #include "controller.h"
    
    Controller::Controller() {
        iWV= new InterfaceWaterVeg();
        statistics= new Statistics();
        stat_ptr=statistics;
    }
    
    void Controller::start(TForm1& guiStart){
    
         gui_ptr=&guiStart;
         [b]contr_ptr = this;[/b]
         startOneParamSet(0);
    
        //startOneParamSet enthält u.a. in aufgerufenen Methoden den Aufruf:
        statistics->calculateRelWater();
    }
    
    //------------------Datei globalVariables.h----------------------------
    #ifndef globalVariablesH
    #define globalVariablesH
    
    #include "controller.h"
    #include "InterfaceWaterVeg.h"
    #include "Statistics.h"
    
    TForm1 *gui_ptr;
    Controller *contr_ptr; 
    Statistics *stat_ptr;
    
    #endif
    
    //-------------Datei Statistics.cpp------------------------
    #include "Statistics.h"
    #include "globalVariables.h"
    
    void Statistics::calculateRelWater() {
         contr_ptr->iWV->relWaterTop=0.0;   
         //iWV und relWaterTop sind Instanzvariablen (iWV ein Objekt, relWaterTop ein double)
         //...
    }
    

    Wenn ich es mit dem zweiten Fettgedruckten laufen lasse, wird unmittelbar nach dieser Anweisung Folgendes im Debugger angezeigt:
    this: Controller * const :0012F39C : : 0041896C und die Instanzvariablen haben offenbar einen Wert
    contr_ptr. Controller * :00418960 : NULL und bei den Instanzvariablen steht überall ein „????“

    Egal, welche der beiden fettgedruckten Anweisungen ich nehme: wenn ich an der Stelle Statistics::calculateRelWater() bei der ersten Zuweisung bin, fliege ich raus (Exception der Klasse EAccessViolation, Zugriffsverletzung bei Adresse 004141F3)
    Ich hab keine Idee, was falsch ist. Kann mir hier jemand weiterhelfen?
    Vielen Dank!
    Susie

    P.S.: Kann man den Text hier auch farbig markieren? Wäre dann ein bißchen einfacher zu erklären, was ich meine...



  • Mit cpp statt code bekommst du Syntaxhighlighting.

    So wie der Code aussieht solltest du ihn meines Erachtens gar nicht durch den Linker bekommen. Die ganzen Zeiger in globalVariables werden in jeder Übersetzungseinheit definiert, was ganz offenbar die Regel, dass alles nur einmal definiert wird (ODR) verletzt. Oder überseh ich da was?

    Jedenfalls solltest du für Ordnung schaffen und die Zeiger mit extern deklarieren und in genau einer .cpp-Datei dann definieren.



  • Danke für die Antwort!
    Hm, ich dachte, durch das

    #ifndef globalVariablesH
    #define globalVariablesH 
    ...
    #endif
    

    in globalVariables.h wird verhindert, daß es mehrfach definiert wird (früher hatte ich nämlich tatsächlich mal Linkerfehler gehabt, auch an ganz anderen Stellen, weil ich da das #ifndef usw. noch nicht drin hatte).
    Oh je, ich hoffe, daß es noch eine andere Lösung gibt, denn das mit dem extern deklarieren hab ich nie richtig verstanden. Vielleicht hat ja noch jemand eine Idee...



  • Hab grad nochmal nachgeschaut, ich bekomme schon eine Linker-Warnung:
    [Linker Warnung] Public symbol '_contr_ptr' defined in both module E:\PROJEKT\VERSION2008_03_20\START.OBJ and E:\PROJEKT\VERSION2008_03_20\CONTROLLER.OBJ

    Aber die hatte ich vorher auch schon gehabt mit anderen Variablen, aber übersetzt wurde es trotzdem (seit ich das mit dem #ifndef usw. reingetan habe) und es lief auch.



  • Oh je, ich hoffe, daß es noch eine andere Lösung gibt, denn das mit dem extern deklarieren hab ich nie richtig verstanden.

    Dann solltest du das schleunigst nachholen...

    Schau dir z.B. mal die Definition der globalen Variablen 'Form1' an:

    // in Form1.h
    extern PACKAGE TForm *Form1;
    
    // in Form1.cpp
    TForm *Form1;
    

    In Header-Dateien werden Variablen nur deklariert, d.h. nur der Name (und Typ) dafür bekannt gemacht (mittels extern).
    Aber in genau einer Source-Datei muß dann diese Variable auch definiert werden, d.h. Speicherplatz dafür reserviert werden (ohne extern).

    Aber eigentlich sind globale Variablen böse und du solltest dir andere Mechanismen zur Variablenübergabe überlegen, z.B. als Parameter im Konstruktor oder eine Setter- und Getter-Methode dafür anlegen.



  • Hallo,

    danke, ja, jetzt klappt es anscheinend wieder. Da hab ich ja noch einiges an meinem Code aufzuräumen, denn ich hab noch mind. eine weitere Stelle im Programm, wo sowas auftaucht. Schadet es denn, wenn es solch eine Linker-Warnung gibt, aber das Programm trotzdem scheinbar richtig läuft? Oder ist das eine tickende Zeitbombe?
    Ich hab es jetzt so geändert, daß ich in allen .cpp-Dateien es so deklariert habe:

    extern Controller *contr_ptr;
    

    und globalVariables.h unverändert, aber ich include es nicht mehr in den anderen Dateien. Das ist doch dann so ok?!

    Allerdings versteh ich eines nicht: Ich dachte, dadurch, daß ich die Definition mit #include reinhole und

    #ifndef globalVariablesH
    #define globalVariablesH
    ...
    #endif
    

    davor schreibe, verhindere ich, daß es mehrmals definiert wird?!

    Hm, nee, ich brauche in einer Datei eine Definition und in allen anderen Dateien eine Deklaration. Dann kann das mit dem #include und dem #if-#endif-Konstrukt mir da wohl nicht weiterhelfen, weil ich dann überall dasselbe include. Aber wozu gibt es dann das #if-#endif-Konstrukt? Irgendwie verhake ich mich an der Stelle in meinen Gedanken.

    Und na ja, das mit den globalen Variablen muß ich wenigstens vorerst mal so lassen (sind auch nur etwa 4 Objekte)
    Jedenfalls danke nochmal und schöne Restostern!



  • Nein, du hast es genau falsch herum gemacht:
    In Header-Datei ".h":

    extern Controller *contr_ptr;
    

    und in Source-Datei ".cpp" die einzige Definition:

    Controller *contr_ptr;
    

    Die Include-Guards verhindern nur, daß die selbe Header-Datei mehrfach pro Source-Datei eingebunden wird (direkt oder indirekt), aber nicht über alle Source-Dateien hinweg.



  • Hm, ok 😉

    Allerdings krieg ich beim Umsortieren in die .h-Dateien eine Menge Fehlermeldungen, die wohl daran liegen, daß ich die anderen .h-Dateien nicht richtig eingebunden habe.
    Wie ist das denn, gibt es so eine generelle Regel, wo man .h-Dateien einbinden sollte, in die .h- oder in die .cpp-Datei? Also, wenn ich auf Variablen usw. einer Datei B in einer Datei A zugreifen möchte, wohin schreibe ich dann #include B.h, in A.h oder in A.cpp?



  • Ist es denn nicht auch egal, ob ich die extern-Deklarationen in der .cpp- oder in der .h-Datei drinhabe? Denn ich schreibe in dem Fall die Deklaration ja deswegen, damit ich sie in der jeweiligen .cpp-Datei verwenden kann.
    Im Gegensatz zu sonst, wo ich die Sachen ja deswegen in die .h-Datei schreibe, weil sie in der .cpp-Datei definiert werden und und die zugehörigen Deklarationen in der .h-Datei dazu dienen, daß sie woanders verwendet werden können (indem man dort eben die .h-Datei einbindet)? Oder lieg ich damit falsch?

    Denn ich hab jetzt resigniert: Wenn es doch läuft, wenn ich die extern-Deklarationen in der .cpp-Datei habe, aber nicht, wenn ich es in der .h-Datei habe, was spricht dann dagegen, es in die .cpp-Datei zu schreiben?!

    Wenn es so nicht schön ist, muß ich irgendwann mal in Ruhe gucken, aber momentan stehe ich anderweitig unter Zeitdruck...


Anmelden zum Antworten