Malloc auf Array? Globale Variablen?



  • Die Warnung vor globalen Variablen ist berechtigt.

    Oftmals führen globale Variablen, die aus Bequemlichkeit angelegt wurden,
    wie ein Buffer für irgendwelche ''temporären'' Abeitsvariablen zu äußerst interessanten Nebeneffekten, da sie an Stellen modifiziert werden an denen man es nicht erwartet.

    int glob_tmpdat;
    
    func1(...)
    {
    int i;
     glob_tmpdat=5;
     for (i=0;i<glob_tmpdat;i++)
      {
       func2("Teststring");
      }
    }
    
    func2(char *s)
    {
    int i
    ....
     glob_tmpdat=strlen(s);
    
    for (i=0;i<glob_tmpdat;i++)
      s[i]=to_upper(s[i]); 
    ......
    }
    

    Typischer Fehler mit globalen Variablen genau solche Nebeneffekte führen zu äußert langen Debugsitzungen.

    Der Einsatz von globalen Variablen minimiert die Portabilität von Funktionen.

    ------------------------------

    Wenn beim ProgrammDesign globale Daten mitgeplant werden, und auch der Zugriff
    geregelt wird kann, es viele Arbeiten auch deutlich einfacher machen.

    Inzwischen bietet da C++ einen vernünftigen Ansatz durch das Klassenkonzept.
    Die Daten werden als private in einer Klasse definiert. Es wird eine globale Instanz der Klasse erzeugt und im Programm kann man auf diese dann nur über die Klassenmembers zugreifen. Auf diese Weise ist ''unnötige'' Übergabe von Daten an Funktionen eingespart. Allerdings sind solche Funktionen nicht portabel da sie auf diese globalen Variablen angewiesen sind



  • PAD schrieb:

    Oftmals führen globale Variablen, die aus Bequemlichkeit angelegt wurden, wie ein Buffer für irgendwelche ''temporären'' Abeitsvariablen zu äußerst interessanten Nebeneffekten, da sie an Stellen modifiziert werden an denen man es nicht erwartet.

    Ich erwarte von Programmen, die nicht richtig funktionieren (warum sollte ich sonst den Quelltext anfassen?) vorsichtshalber überhauptnichts. Wildes Herumspekulieren ist deplaziert, wenn ich herausfinden soll, was das Programm/die Funktion eigentlich macht.

    Typischer Fehler mit globalen Variablen genau solche Nebeneffekte führen zu äußert langen Debugsitzungen.

    Der Fehler ist, dass Du Dich auf etwas verlässt. Nichts sonst.
    Dass diese 'globalen Variablen' (so etwas gibt es in C nicht) auch falsch eingesetzt werden können ist jetzt keine allzu atemberaubende Neuigkeit.

    Wenn beim ProgrammDesign globale Daten mitgeplant werden, und auch der Zugriff geregelt wird kann, es viele Arbeiten auch deutlich einfacher machen.

    Genau. Man darf diese 'globalen' Datenmengen trotzdem so klein wie möglich halten.

    Inzwischen bietet da C++ einen vernünftigen Ansatz durch das Klassenkonzept.
    Die Daten werden als private in einer Klasse definiert. Es wird eine globale Instanz der Klasse erzeugt und im Programm kann man auf diese dann nur über die Klassenmembers zugreifen. Auf diese Weise ist ''unnötige'' Übergabe von Daten an Funktionen eingespart. Allerdings sind solche Funktionen nicht portabel da sie auf diese globalen Variablen angewiesen sind

    Kannst Du etwas näher ausführen, wie man mithilfe der Klassenmembers auf die privaten Daten einer globalen Instanz einer Klasse unnötige Übergabe von Daten an Funktionen einspart und warum diese Funktionen dann von globalen Variablen, die das Konzept ja eigentlich vermeiden wollte, abhängt?



  • @ Daniel E.

    Es geht hier nicht nur um Programme die Fehler haben sondern auch um welche die gerade in der Entwicklung sind.

    Die Fragestellung von Holgie beinhaltet auch die Frage warum man keine globalen
    Variablen einsetzen soll. Was ich dazu ausführte waren die typischen Fehler die neben Philosopiefragen einen dazu bringen die Nutzung von globalen Variablen zu minimieren. 😃 Atemberaubend ist es nicht 😃 Neuigkeit ist es nicht 😃 , aber neben Pointern eins der Probleme die eine Menge Zeit brauchen. Speziell wenn man Programme wartern mußt. 😡

    👎 Eine von den schönen Fehlern war. In einem bestehenden Programm hat jemand die Laufvariable i als global deklariert.

    Um einen Feature einzubauen hat ein Kollege eine locale Variable i benötigt und vergessen Sie zu deklarieren, somit wurde die globale genutzt, was zu tollen Effekten geführt hat. Weil im ersten Moment kommt keiner auf so einen Blödsinn.

    class test
    {
    privat:
    int i;
    public:
    void setValue(int val);
    int getValue(void);
    .... Konstruktoren,...
    }
    
    test a;
    
    main()
    {
    int b;
    .....
    a.setValue(33);
    
    b=a.getValue();
    ...
    }
    
    function1(..)
    {
    ...
    a.setValue(44);
    }
    // Hoffentlich sind keine Typos drin, habe den Code nicht getestet
    

    Hier wird ein Datum i aus der Klasse test global genutzt. Die Wahrscheinlichkeit das jemand hier eine Fehlnutzung vornimmt ist für mich geringer als mit einer globalen Variablen i.



  • @Holgie

    madys Beispiel ist nicht genau die Antwort auf deine Frage.

    Wenn du ein char Blubb[SIZE_A][SIZE_B] verwenden willst, musst du einfach

    char *Blubb = malloc( SIZE_A * SIZE_B);

    verwenden.
    wobei SIZE_A und SIZE_B hier Konstanten oder Variablen sein können.

    (und natürlich den Rückgabewert auf NULL testen)



  • Geo schrieb:

    @Holgie

    madys Beispiel ist nicht genau die Antwort auf deine Frage.

    Wenn du ein char Blubb[SIZE_A][SIZE_B] verwenden willst, musst du einfach

    char *Blubb = malloc( SIZE_A * SIZE_B);

    verwenden.
    wobei SIZE_A und SIZE_B hier Konstanten oder Variablen sein können.

    (und natürlich den Rückgabewert auf NULL testen)

    hmmm ... aber so ohne weiteres ist dann ein Zugriff auf das Array mit Blubb[x][y] aber nicht möglich. Von anderen Problemen mal abgesehen



  • Geo schrieb:

    @Holgie

    madys Beispiel ist nicht genau die Antwort auf deine Frage.

    Wenn du ein char Blubb[SIZE_A][SIZE_B] verwenden willst, musst du einfach

    char *Blubb = malloc( SIZE_A * SIZE_B);

    verwenden.
    wobei SIZE_A und SIZE_B hier Konstanten oder Variablen sein können.

    (und natürlich den Rückgabewert auf NULL testen)

    Das alloziiert aber keinen Speicher fuer 'Blubb[SIZE_A][SIZE_B]'

    mfg
    v R



  • Hab das Beispiel von PAD mal ausführlich nachvollzogen, da ich selbst auch immer den einfachen Weg gehe und jede Menge globale Variablen anlege.

    Hier das Beispiel von PAD zum direkten übernehmen: int iTest != global

    Unit1.cpp

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "MyClass.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    // *** Definition des Objekts "a" der Klasse TMyClass ***
    TMyClass a;
    
    // *** Funktions-Deklarationen ***
    void Function1( void );
    //void Function2( void );
    //...
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    // Setze Value direkt
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     a.setValue( StrToInt( Edit1->Text ) );
    }
    //---------------------------------------------------------------------------
    
    // Get Value
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     int b;
    
     b = a.getValue();
     Label1->Caption = IntToStr( b );
    }
    //---------------------------------------------------------------------------
    
    // Setze Value via Function1()
    void __fastcall TForm1::Button3Click(TObject *Sender)
    {
     Function1();
    }
    //---------------------------------------------------------------------------
    
    void Function1( void )
    {
     a.setValue( StrToInt( Form1->Edit1->Text ) + 5 );
    }
    //---------------------------------------------------------------------------
    

    Unit1.h

    //---------------------------------------------------------------------------
    
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
            TButton *Button1;
            TButton *Button2;
            TButton *Button3;
            TLabel *Label1;
            TEdit *Edit1;
            void __fastcall Button1Click(TObject *Sender);
            void __fastcall Button2Click(TObject *Sender);
            void __fastcall Button3Click(TObject *Sender);
    private:	// Anwender-Deklarationen
    public:		// Anwender-Deklarationen
            __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    MyClass.cpp

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "MyClass.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
    
    // *** Definition des Konstruktors TMyClass ***
    __fastcall TMyClass::TMyClass( void )
    {
    }
    //---------------------------------------------------------------------------
    
    // *** Methodendefinitionen von TMyClass ***
    void __fastcall TMyClass::setValue( int val )
    {
     iTest = val;
    }
    //---------------------------------------------------------------------------
    
    // *** Methodendefinitionen von TMyClass ***
    __fastcall TMyClass::getValue( void )
    {
     return iTest;
    }
    //---------------------------------------------------------------------------
    

    MyClass.h

    //---------------------------------------------------------------------------
    
    #ifndef MyClassH
    #define MyClassH
    //---------------------------------------------------------------------------
    // *** Deklaration der Klasse TMyClass ***
    class TMyClass
    {
    private:
        // *** Eigenschaften ***
        int iTest;
    
    public:
        // *** Methoden ***
        void __fastcall setValue( int val );
        __fastcall getValue( void );
    
        // *** Konstruktor ***
        __fastcall TMyClass( void );
    };
    //---------------------------------------------------------------------------
    #endif
    

    Gruß WoWe



  • was heisst fuer dich != global?

    du hast fuer mich 2 globale variablen
    a und Form1
    Form1 muss wohl global sein, da es die VCL vorschreibt

    aber a??
    du hast i in eine klasse gesteckt und nennst es nun nicht mehr global.
    genau das ist aber bloedsinn.

    ich kann immer noch i veraendern wie ich will, ich muss zwar getter und setter verwenden, das ist ne spur besser als richtig global, aber immer noch verdammt mies.

    btw:

    __fastcall TMyClass::getValue( void )

    syntax fehler
    return value fehlt.

    und lass das void weg, in C++ schreibt man das nicht!

    btw: Function1() ist ne miese funktion mit seiteneffekten...



  • Hmm, also ich war mir sicher das diese Art richtig ist um "a" als globale Variable zu umgehen.

    Dann hab ich die Bitte an dich und korrigiere das Beispiel von mir so das es richtig ist (nicht nur für mich) !

    Gruß WoWe



  • machen wirs so:

    du gibts mir ein beispiel wo man deiner meinung nach eine globale variable verwenden muss und wir diskutieren es dann aus (wo die nachteile der globalen variablen liegen, wo die vorteile liegen, was man am design aendern koennte, etc).

    dein ganzes beispiel ist naehmlich n bisschen bloed.



  • Naja, dann nehmen wir einfach an, dass außer der Variable iTest mehrere Variablen in mehreren Funktionen über mehrere Formulare/Units gelesen und aktualisiert werden. Das sollte ja kein nutzbares Programm werden sondern nur ein Beispiel wie ich mit Variablen arbeiten kann ohne sie global anzulegen und dann mit extern drauf zugreifen.



  • ich wuerde sagen:
    MVC-Modell
    mit Observer-Pattern

    BTW:
    du solltest wirklich nicht die VCL verwenden, wenn du solchen code schreibst...

    globale variablen, funktionen mit seiteneffekten, code in den forumlaren,... (grausam)



  • hab ich was übersehen oder wieso tuts statt dem *** gehampel kein simples

    char* mspeicher =(char*)malloc(sizeof(char[20][40]));
    

    😕



  • dreaddy schrieb:

    hab ich was übersehen oder wieso tuts statt dem *** gehampel kein simples

    char* mspeicher =(char*)malloc(sizeof(char[20][40]));
    

    😕

    Weil Du dann immer noch nicht ohne weiteres mit mspeicher[x][y] auf die einzelnen Elemente zugreifen kannst.



  • Daniel E. schrieb:

    Dass diese 'globalen Variablen' (so etwas gibt es in C nicht) auch falsch eingesetzt werden können ist jetzt keine allzu atemberaubende Neuigkeit.

    hae? warum gibt es in C keine globalen Variablen? 😕



  • spitzenbleistift schrieb:

    Daniel E. schrieb:

    Dass diese 'globalen Variablen' (so etwas gibt es in C nicht) auch falsch eingesetzt werden können ist jetzt keine allzu atemberaubende Neuigkeit.

    hae? warum gibt es in C keine globalen Variablen? 😕

    Weil es im Standard keine Beschreibung für "globale Variablen" gibt. Aber es dürfte klar sein was damit gemeint ist, wenn von "globalen Variablen" die Rede ist...



  • mady schrieb:

    spitzenbleistift schrieb:

    Daniel E. schrieb:

    Dass diese 'globalen Variablen' (so etwas gibt es in C nicht) auch falsch eingesetzt werden können ist jetzt keine allzu atemberaubende Neuigkeit.

    hae? warum gibt es in C keine globalen Variablen? 😕

    Weil es im Standard keine Beschreibung für "globale Variablen" gibt. Aber es dürfte klar sein was damit gemeint ist, wenn von "globalen Variablen" die Rede ist...

    heisst das, dass laut Standard eine Definition ausserhalb einer Funktion illegal ist?



  • Nein. Aber das ist dann nicht global im Sinne von "überall sichtbar". (ich persönlich halte das allerdings für Haarspalterei)



  • spitzenbleistift schrieb:

    heisst das, dass laut Standard eine Definition ausserhalb einer Funktion illegal ist?

    int a; void f() {} int b;
    

    Sowohl a als auch b liegen außerhalb des Sichtbarkeitsbereiches von f. Ergo sind sie beide 'global'. Allerdings ist b in f unsichtbar. Man kann sich jetzt dazu hinreißen lassen, zu behaupten, a sei 'globaler' als b. Das ist optimalstes Dummdeutsch.


Anmelden zum Antworten